@sonicjs-cms/core 2.3.8 → 2.3.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-Q52ZQFMB.js → chunk-3YNNVSMC.js} +21 -34
- package/dist/chunk-3YNNVSMC.js.map +1 -0
- package/dist/{chunk-KNSBZMAH.js → chunk-74RYBO6J.js} +4 -5
- package/dist/chunk-74RYBO6J.js.map +1 -0
- package/dist/{chunk-ES3BRZQJ.cjs → chunk-7FOAMNTI.cjs} +29 -42
- package/dist/chunk-7FOAMNTI.cjs.map +1 -0
- package/dist/{chunk-IZYEXDBF.js → chunk-EIE35JCC.js} +4 -4
- package/dist/{chunk-IZYEXDBF.js.map → chunk-EIE35JCC.js.map} +1 -1
- package/dist/{chunk-VE5WH254.js → chunk-HDSRB23N.js} +18 -16
- package/dist/chunk-HDSRB23N.js.map +1 -0
- package/dist/{chunk-CSEI667V.cjs → chunk-HTJLBF6F.cjs} +200 -198
- package/dist/chunk-HTJLBF6F.cjs.map +1 -0
- package/dist/{chunk-SDT3HNLI.cjs → chunk-IB6UBZVD.cjs} +4 -5
- package/dist/chunk-IB6UBZVD.cjs.map +1 -0
- package/dist/{chunk-NAYD76QF.cjs → chunk-ILZ3DP4I.cjs} +15 -6
- package/dist/chunk-ILZ3DP4I.cjs.map +1 -0
- package/dist/{chunk-ZMSYKV62.cjs → chunk-K6BFUYJH.cjs} +5 -5
- package/dist/{chunk-ZMSYKV62.cjs.map → chunk-K6BFUYJH.cjs.map} +1 -1
- package/dist/{chunk-5RKQB2JG.js → chunk-KQCYQKSV.js} +8 -6
- package/dist/chunk-KQCYQKSV.js.map +1 -0
- package/dist/{chunk-OTUKT2WY.js → chunk-NTXPL746.js} +2 -2
- package/dist/{chunk-OTUKT2WY.js.map → chunk-NTXPL746.js.map} +1 -1
- package/dist/{chunk-KXMX4F2L.cjs → chunk-OJ5WUCSH.cjs} +7 -7
- package/dist/{chunk-KXMX4F2L.cjs.map → chunk-OJ5WUCSH.cjs.map} +1 -1
- package/dist/{chunk-7KCDFDRI.cjs → chunk-P3XDZL6Q.cjs} +3 -4
- package/dist/chunk-P3XDZL6Q.cjs.map +1 -0
- package/dist/{chunk-AUVR77XH.cjs → chunk-P6NMVNJJ.cjs} +2 -2
- package/dist/{chunk-AUVR77XH.cjs.map → chunk-P6NMVNJJ.cjs.map} +1 -1
- package/dist/{chunk-QNWYQZ55.js → chunk-REY542YK.js} +3 -3
- package/dist/{chunk-QNWYQZ55.js.map → chunk-REY542YK.js.map} +1 -1
- package/dist/{chunk-YU6QFFI4.cjs → chunk-RIOIKM3Y.cjs} +8 -6
- package/dist/chunk-RIOIKM3Y.cjs.map +1 -0
- package/dist/{chunk-7CXL5K7N.js → chunk-SGAG6FD3.js} +15 -6
- package/dist/chunk-SGAG6FD3.js.map +1 -0
- package/dist/{chunk-RRKXFGIO.js → chunk-X7ZAEI5S.js} +3 -4
- package/dist/chunk-X7ZAEI5S.js.map +1 -0
- package/dist/index.cjs +145 -145
- package/dist/index.js +14 -14
- package/dist/middleware.cjs +24 -24
- package/dist/middleware.js +3 -3
- package/dist/migrations-DQ74P6V4.cjs +13 -0
- package/dist/{migrations-5L2MGJTP.cjs.map → migrations-DQ74P6V4.cjs.map} +1 -1
- package/dist/migrations-YAFC5JVO.js +4 -0
- package/dist/{migrations-U5QBY3BZ.js.map → migrations-YAFC5JVO.js.map} +1 -1
- package/dist/routes.cjs +28 -28
- package/dist/routes.js +8 -8
- package/dist/services.cjs +29 -29
- package/dist/services.d.cts +3 -4
- package/dist/services.d.ts +3 -4
- package/dist/services.js +4 -4
- package/dist/{telemetry-BFBIjBxK.d.cts → telemetry-UiD1i9GS.d.cts} +0 -1
- package/dist/{telemetry-BFBIjBxK.d.ts → telemetry-UiD1i9GS.d.ts} +0 -1
- package/dist/templates.cjs +17 -17
- package/dist/templates.js +2 -2
- package/dist/types.d.cts +1 -1
- package/dist/types.d.ts +1 -1
- package/dist/utils.cjs +20 -20
- package/dist/utils.d.cts +1 -1
- package/dist/utils.d.ts +1 -1
- package/dist/utils.js +2 -2
- package/package.json +2 -3
- package/dist/chunk-5RKQB2JG.js.map +0 -1
- package/dist/chunk-7CXL5K7N.js.map +0 -1
- package/dist/chunk-7KCDFDRI.cjs.map +0 -1
- package/dist/chunk-CSEI667V.cjs.map +0 -1
- package/dist/chunk-ES3BRZQJ.cjs.map +0 -1
- package/dist/chunk-KNSBZMAH.js.map +0 -1
- package/dist/chunk-NAYD76QF.cjs.map +0 -1
- package/dist/chunk-Q52ZQFMB.js.map +0 -1
- package/dist/chunk-RRKXFGIO.js.map +0 -1
- package/dist/chunk-SDT3HNLI.cjs.map +0 -1
- package/dist/chunk-VE5WH254.js.map +0 -1
- package/dist/chunk-YU6QFFI4.cjs.map +0 -1
- package/dist/migrations-5L2MGJTP.cjs +0 -13
- package/dist/migrations-U5QBY3BZ.js +0 -4
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/schemas/index.ts","../src/routes/api-content-crud.ts","../src/routes/api.ts","../src/routes/api-media.ts","../src/routes/api-system.ts","../src/routes/admin-api.ts","../src/templates/pages/auth-login.template.ts","../src/templates/pages/auth-register.template.ts","../src/services/auth-validation.ts","../src/routes/auth.ts","../src/routes/test-cleanup.ts","../src/templates/pages/admin-content-form.template.ts","../src/templates/components/dynamic-field.template.ts","../src/plugins/sdk/plugin-builder.ts","../src/plugins/available/tinymce-plugin/index.ts","../src/plugins/core-plugins/quill-editor/index.ts","../src/plugins/available/easy-mdx/index.ts","../src/templates/pages/admin-content-list.template.ts","../src/templates/components/version-history.template.ts","../src/middleware/plugin-middleware.ts","../src/routes/admin-content.ts","../src/templates/pages/admin-profile.template.ts","../src/templates/components/alert.template.ts","../src/templates/pages/admin-activity-logs.template.ts","../src/templates/pages/admin-user-edit.template.ts","../src/templates/components/confirmation-dialog.template.ts","../src/templates/pages/admin-user-new.template.ts","../src/templates/pages/admin-users-list.template.ts","../src/routes/admin-users.ts","../src/templates/components/media-grid.template.ts","../src/templates/pages/admin-media-library.template.ts","../src/templates/components/media-file-details.template.ts","../src/routes/admin-media.ts","../src/templates/pages/admin-plugins-list.template.ts","../src/templates/components/auth-settings-form.template.ts","../src/templates/pages/admin-plugin-settings.template.ts","../src/routes/admin-plugins.ts","../src/templates/pages/admin-logs-list.template.ts","../src/templates/pages/admin-log-details.template.ts","../src/templates/pages/admin-log-config.template.ts","../src/routes/admin-logs.ts","../src/routes/admin-design.ts","../src/routes/admin-checkboxes.ts","../src/templates/pages/admin-testimonials-form.template.ts","../src/routes/admin-testimonials.ts","../src/templates/pages/admin-code-examples-form.template.ts","../src/routes/admin-code-examples.ts","../src/templates/pages/admin-dashboard.template.ts","../src/routes/admin-dashboard.ts","../src/templates/pages/admin-collections-list.template.ts","../src/templates/components/table.template.ts","../src/templates/pages/admin-collections-form.template.ts","../src/routes/admin-collections.ts","../src/templates/pages/admin-settings.template.ts","../src/routes/admin-settings.ts","../src/routes/index.ts"],"names":["Hono","requireAuth","getCacheService","CACHE_CONFIGS","isPluginActive","cors","QueryFilterBuilder","builder","z","requireRole","MigrationService","renderAlert","error","AuthManager","setCookie","html","passwordHash","c","init_admin_layout_catalyst_template","escapeHtml","options","renderConfirmationDialog","getConfirmationDialogScript","renderAdminLayoutCatalyst","renderTable","renderPagination","db","collection","formData","PluginService","tinymcePlugin","renderAdminLayout","sanitizeInput","logActivity","fileValidationSchema","raw","getImageDimensions","getJPEGDimensions","getPNGDimensions","easyMdxPlugin","adminLayoutV2","getLogger","renderDesignPage","renderCheckboxPage","renderTestimonialsList","renderCodeExamplesList","getCoreVersion","metricsTracker","renderForm","tinymceActive","quillActive","mdxeditorActive","result","SettingsService"],"mappings":"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AAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA,MAAA,EAoRpF,IA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;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA,IAAA,EAugBJG,yBAAAA,CAAyB;A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AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA,IAAA,EA2XtD3B,yBAAAA,CAAyB;AAAA,IACzB,EAAA,EAAI,sBAAA;AAAA,IACJ,KAAA,EAAO,cAAA;AAAA,IACP,OAAA,EAAS,2EAAA;AAAA,IACT,WAAA,EAAa,QAAA;AAAA,IACb,UAAA,EAAY,QAAA;AAAA,IACZ,SAAA,EAAW,KAAA;AAAA,IACX,YAAA,EAAc,6BAAA;AAAA,IACd,SAAA,EAAW;AAAA,GACZ,CAAC;;AAAA,IAAA,EAEAC,8BAA6B;AAAA,EAAA,CAAA;AAGjC,EAAA,MAAM,UAAA,GAAsC;AAAA,IAC1C,KAAA;AAAA,IACA,SAAA,EAAW,aAAA;AAAA,IACX,WAAA,EAAa,oBAAA;AAAA,IACb,MAAM,IAAA,CAAK,IAAA;AAAA,IACX,SAAS,IAAA,CAAK,OAAA;AAAA,IACd,OAAA,EAAS;AAAA,GACX;AAEA,EAAA,OAAOC,4CAA0B,UAAU,CAAA;AAC7C;;;ACn/BO,IAAM,sBAAA,GAAyB,IAAIvB,SAAAA;AAG1C,sBAAA,CAAuB,GAAA,CAAI,GAAA,EAAKC,6BAAA,EAAa,CAAA;AAG7C,sBAAA,CAAuB,GAAA,CAAI,GAAA,EAAK,OAAO,CAAA,KAAM;AAC3C,EAAA,IAAI;AACF,IAAA,MAAM,IAAA,GAAO,CAAA,CAAE,GAAA,CAAI,MAAM,CAAA;AACzB,IAAA,MAAM,EAAA,GAAK,EAAE,GAAA,CAAI,EAAA;AACjB,IAAA,MAAM,GAAA,GAAM,IAAI,GAAA,CAAI,CAAA,CAAE,IAAI,GAAG,CAAA;AAC7B,IAAA,MAAM,MAAA,GAAS,GAAA,CAAI,YAAA,CAAa,GAAA,CAAI,QAAQ,CAAA,IAAK,EAAA;AAGjD,IAAA,IAAI,IAAA;AACJ,IAAA,IAAI,OAAA;AACJ,IAAA,IAAI,MAAA,EAAQ;AACV,MAAA,IAAA,GAAO,GAAG,OAAA,CAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAAA,CAMjB,CAAA;AACD,MAAA,MAAM,WAAA,GAAc,IAAI,MAAM,CAAA,CAAA,CAAA;AAC9B,MAAA,MAAM,YAAA,GAAe,MAAM,IAAA,CAAK,IAAA,CAAK,aAAa,WAAA,EAAa,WAAW,EAAE,GAAA,EAAI;AAChF,MAAA,OAAA,GAAU,YAAA,CAAa,OAAA;AAAA,IACzB,CAAA,MAAO;AACL,MAAA,IAAA,GAAO,EAAA,CAAG,QAAQ,uIAAuI,CAAA;AACzJ,MAAA,MAAM,YAAA,GAAe,MAAM,IAAA,CAAK,GAAA,EAAI;AACpC,MAAA,OAAA,GAAU,YAAA,CAAa,OAAA;AAAA,IACzB;AAGA,IAAA,MAAM,cAAA,GAAiB,EAAA,CAAG,OAAA,CAAQ,oFAAoF,CAAA;AACtH,IAAA,MAAM,EAAE,OAAA,EAAS,iBAAA,EAAkB,GAAI,MAAM,eAAe,GAAA,EAAI;AAChE,IAAA,MAAM,cAAc,IAAI,GAAA,CAAA,CAAK,qBAAqB,EAAC,EAAG,IAAI,CAAC,GAAA,KAAa,CAAC,MAAA,CAAO,GAAA,CAAI,aAAa,CAAA,EAAG,MAAA,CAAO,IAAI,KAAK,CAAC,CAAC,CAAC,CAAA;AAEvH,IAAA,MAAM,WAAA,GAAA,CAA6B,OAAA,IAAW,EAAC,EAC5C,MAAA,CAAO,CAAC,GAAA,KAAa,GAAA,IAAO,GAAA,CAAI,EAAE,CAAA,CAClC,GAAA,CAAI,CAAC,GAAA,KAAa;AAEjB,MAAA,IAAI,UAAA,GAAa,CAAA;AACjB,MAAA,IAAI,IAAI,MAAA,EAAQ;AACd,QAAA,IAAI;AACF,UAAA,MAAM,MAAA,GAAS,OAAO,GAAA,CAAI,MAAA,KAAW,QAAA,GAAW,KAAK,KAAA,CAAM,GAAA,CAAI,MAAM,CAAA,GAAI,GAAA,CAAI,MAAA;AAC7E,UAAA,IAAI,MAAA,IAAU,OAAO,UAAA,EAAY;AAC/B,YAAA,UAAA,GAAa,MAAA,CAAO,IAAA,CAAK,MAAA,CAAO,UAAU,CAAA,CAAE,MAAA;AAAA,UAC9C;AAAA,QACF,SAAS,CAAA,EAAG;AAEV,UAAA,UAAA,GAAa,YAAY,GAAA,CAAI,MAAA,CAAO,GAAA,CAAI,EAAE,CAAC,CAAA,IAAK,CAAA;AAAA,QAClD;AAAA,MACF,CAAA,MAAO;AACL,QAAA,UAAA,GAAa,YAAY,GAAA,CAAI,MAAA,CAAO,GAAA,CAAI,EAAE,CAAC,CAAA,IAAK,CAAA;AAAA,MAClD;AAEA,MAAA,OAAO;AAAA,QACL,EAAA,EAAI,MAAA,CAAO,GAAA,CAAI,EAAA,IAAM,EAAE,CAAA;AAAA,QACvB,IAAA,EAAM,MAAA,CAAO,GAAA,CAAI,IAAA,IAAQ,EAAE,CAAA;AAAA,QAC3B,YAAA,EAAc,MAAA,CAAO,GAAA,CAAI,YAAA,IAAgB,EAAE,CAAA;AAAA,QAC3C,aAAa,GAAA,CAAI,WAAA,GAAc,MAAA,CAAO,GAAA,CAAI,WAAW,CAAA,GAAI,KAAA,CAAA;AAAA,QACzD,UAAA,EAAY,MAAA,CAAO,GAAA,CAAI,UAAA,IAAc,CAAC,CAAA;AAAA,QACtC,aAAA,EAAe,GAAA,CAAI,UAAA,GAAa,IAAI,IAAA,CAAK,MAAA,CAAO,GAAA,CAAI,UAAU,CAAC,CAAA,CAAE,kBAAA,EAAmB,GAAI,SAAA;AAAA,QACxF,WAAA,EAAa,UAAA;AAAA,QACb,OAAA,EAAS,IAAI,OAAA,KAAY;AAAA,OAC3B;AAAA,IACF,CAAC,CAAA;AAEH,IAAA,MAAM,QAAA,GAAoC;AAAA,MACxC,WAAA;AAAA,MACA,MAAA;AAAA,MACA,MAAM,IAAA,GAAO;AAAA,QACX,MAAM,IAAA,CAAK,KAAA;AAAA,QACX,OAAO,IAAA,CAAK,KAAA;AAAA,QACZ,MAAM,IAAA,CAAK;AAAA,OACb,GAAI,KAAA,CAAA;AAAA,MACJ,OAAA,EAAS,CAAA,CAAE,GAAA,CAAI,YAAY;AAAA,KAC7B;AAEA,IAAA,OAAO,CAAA,CAAE,IAAA,CAAK,yBAAA,CAA0B,QAAQ,CAAC,CAAA;AAAA,EACnD,SAAS,KAAA,EAAO;AACd,IAAA,OAAA,CAAQ,KAAA,CAAM,+BAA+B,KAAK,CAAA;AAClD,IAAA,MAAM,eAAe,KAAA,YAAiB,KAAA,GAAQ,KAAA,CAAM,OAAA,GAAU,OAAO,KAAK,CAAA;AAC1E,IAAA,OAAO,CAAA,CAAE,IAAA,CAAKc,SAAAA,CAAAA,8BAAAA,EAAqC,YAAY,CAAA,IAAA,CAAM,CAAA;AAAA,EACvE;AACF,CAAC,CAAA;AAGD,sBAAA,CAAuB,GAAA,CAAI,MAAA,EAAQ,OAAO,CAAA,KAAM;AAC9C,EAAA,MAAM,IAAA,GAAO,CAAA,CAAE,GAAA,CAAI,MAAM,CAAA;AACzB,EAAA,MAAM,EAAA,GAAK,EAAE,GAAA,CAAI,EAAA;AAGjB,EAAA,MAAM,CAAC,aAAA,EAAe,WAAA,EAAa,eAAe,CAAA,GAAI,MAAM,QAAQ,GAAA,CAAI;AAAA,IACtEX,eAAAA,CAAe,IAAI,gBAAgB,CAAA;AAAA,IACnCA,eAAAA,CAAe,IAAI,cAAc,CAAA;AAAA,IACjCA,eAAAA,CAAe,IAAI,UAAU;AAAA,GAC9B,CAAA;AAED,EAAA,OAAA,CAAQ,IAAI,2CAAA,EAA6C;AAAA,IACvD,OAAA,EAAS,aAAA;AAAA,IACT,KAAA,EAAO,WAAA;AAAA,IACP,OAAA,EAAS;AAAA,GACV,CAAA;AAED,EAAA,MAAM,QAAA,GAA+B;AAAA,IACnC,MAAA,EAAQ,KAAA;AAAA,IACR,MAAM,IAAA,GAAO;AAAA,MACX,MAAM,IAAA,CAAK,KAAA;AAAA,MACX,OAAO,IAAA,CAAK,KAAA;AAAA,MACZ,MAAM,IAAA,CAAK;AAAA,KACb,GAAI,MAAA;AAAA,IACJ,OAAA,EAAS,CAAA,CAAE,GAAA,CAAI,YAAY,CAAA;AAAA,IAC3B,aAAA,EAAe;AAAA,MACb,OAAA,EAAS,aAAA;AAAA,MACT,KAAA,EAAO,WAAA;AAAA,MACP,OAAA,EAAS;AAAA;AACX,GACF;AAEA,EAAA,OAAO,CAAA,CAAE,IAAA,CAAK,wBAAA,CAAyB,QAAQ,CAAC,CAAA;AAClD,CAAC,CAAA;AAGD,sBAAA,CAAuB,IAAA,CAAK,GAAA,EAAK,OAAO,CAAA,KAAM;AAC5C,EAAA,IAAI;AACF,IAAA,MAAM,QAAA,GAAW,MAAM,CAAA,CAAE,GAAA,CAAI,QAAA,EAAS;AACtC,IAAA,MAAM,IAAA,GAAO,QAAA,CAAS,GAAA,CAAI,MAAM,CAAA;AAChC,IAAA,MAAM,WAAA,GAAc,QAAA,CAAS,GAAA,CAAI,aAAa,CAAA;AAC9C,IAAA,MAAM,WAAA,GAAc,QAAA,CAAS,GAAA,CAAI,aAAa,CAAA;AAG9C,IAAA,MAAM,MAAA,GAAS,CAAA,CAAE,GAAA,CAAI,MAAA,CAAO,YAAY,CAAA,KAAM,MAAA;AAG9C,IAAA,IAAI,CAAC,IAAA,IAAQ,CAAC,WAAA,EAAa;AACzB,MAAA,MAAM,QAAA,GAAW,qCAAA;AACjB,MAAA,IAAI,MAAA,EAAQ;AACV,QAAA,OAAO,EAAE,IAAA,CAAKW,SAAAA;AAAA;AAAA,YAAA,EAER,QAAQ;AAAA;AAAA,QAAA,CAEb,CAAA;AAAA,MACH,CAAA,MAAO;AAEL,QAAA,OAAO,CAAA,CAAE,SAAS,wBAAwB,CAAA;AAAA,MAC5C;AAAA,IACF;AAGA,IAAA,IAAI,CAAC,cAAA,CAAe,IAAA,CAAK,IAAI,CAAA,EAAG;AAC9B,MAAA,MAAM,QAAA,GAAW,gFAAA;AACjB,MAAA,IAAI,MAAA,EAAQ;AACV,QAAA,OAAO,EAAE,IAAA,CAAKA,SAAAA;AAAA;AAAA,YAAA,EAER,QAAQ;AAAA;AAAA,QAAA,CAEb,CAAA;AAAA,MACH,CAAA,MAAO;AACL,QAAA,OAAO,CAAA,CAAE,SAAS,wBAAwB,CAAA;AAAA,MAC5C;AAAA,IACF;AAEA,IAAA,MAAM,EAAA,GAAK,EAAE,GAAA,CAAI,EAAA;AAGjB,IAAA,MAAM,YAAA,GAAe,EAAA,CAAG,OAAA,CAAQ,2CAA2C,CAAA;AAC3E,IAAA,MAAM,WAAW,MAAM,YAAA,CAAa,IAAA,CAAK,IAAI,EAAE,KAAA,EAAM;AAErD,IAAA,IAAI,QAAA,EAAU;AACZ,MAAA,MAAM,QAAA,GAAW,6CAAA;AACjB,MAAA,IAAI,MAAA,EAAQ;AACV,QAAA,OAAO,EAAE,IAAA,CAAKA,SAAAA;AAAA;AAAA,YAAA,EAER,QAAQ;AAAA;AAAA,QAAA,CAEb,CAAA;AAAA,MACH,CAAA,MAAO;AACL,QAAA,OAAO,CAAA,CAAE,SAAS,wBAAwB,CAAA;AAAA,MAC5C;AAAA,IACF;AAGA,IAAA,MAAM,WAAA,GAAc;AAAA,MAClB,IAAA,EAAM,QAAA;AAAA,MACN,UAAA,EAAY;AAAA,QACV,KAAA,EAAO;AAAA,UACL,IAAA,EAAM,QAAA;AAAA,UACN,KAAA,EAAO,OAAA;AAAA,UACP,QAAA,EAAU;AAAA,SACZ;AAAA,QACA,OAAA,EAAS;AAAA,UACP,IAAA,EAAM,QAAA;AAAA,UACN,KAAA,EAAO,SAAA;AAAA,UACP,MAAA,EAAQ;AAAA,SACV;AAAA,QACA,MAAA,EAAQ;AAAA,UACN,IAAA,EAAM,QAAA;AAAA,UACN,KAAA,EAAO,QAAA;AAAA,UACP,IAAA,EAAM,CAAC,OAAA,EAAS,WAAA,EAAa,UAAU,CAAA;AAAA,UACvC,OAAA,EAAS;AAAA;AACX,OACF;AAAA,MACA,QAAA,EAAU,CAAC,OAAO;AAAA,KACpB;AAGA,IAAA,MAAM,YAAA,GAAe,OAAO,UAAA,EAAW;AACvC,IAAA,MAAM,GAAA,GAAM,KAAK,GAAA,EAAI;AAErB,IAAA,MAAM,UAAA,GAAa,GAAG,OAAA,CAAQ;AAAA;AAAA;AAAA,IAAA,CAG7B,CAAA;AAED,IAAA,MAAM,UAAA,CAAW,IAAA;AAAA,MACf,YAAA;AAAA,MACA,IAAA;AAAA,MACA,WAAA;AAAA,MACA,WAAA,IAAe,IAAA;AAAA,MACf,IAAA,CAAK,UAAU,WAAW,CAAA;AAAA,MAC1B,CAAA;AAAA;AAAA,MACA,GAAA;AAAA,MACA;AAAA,MACA,GAAA,EAAI;AAGN,IAAA,IAAI,CAAA,CAAE,IAAI,QAAA,EAAU;AAClB,MAAA,IAAI;AACF,QAAA,MAAM,CAAA,CAAE,GAAA,CAAI,QAAA,CAAS,MAAA,CAAO,uBAAuB,CAAA;AACnD,QAAA,MAAM,EAAE,GAAA,CAAI,QAAA,CAAS,MAAA,CAAO,CAAA,iBAAA,EAAoB,IAAI,CAAA,CAAE,CAAA;AAAA,MACxD,SAAS,CAAA,EAAG;AACV,QAAA,OAAA,CAAQ,KAAA,CAAM,yBAAyB,CAAC,CAAA;AAAA,MAC1C;AAAA,IACF;AAEA,IAAA,IAAI,MAAA,EAAQ;AACV,MAAA,OAAO,EAAE,IAAA,CAAKA,SAAAA;AAAA;AAAA;AAAA;AAAA;AAAA,yDAAA,EAKuC,YAAY,CAAA;AAAA;AAAA;AAAA;AAAA,MAAA,CAIhE,CAAA;AAAA,IACH,CAAA,MAAO;AAEL,MAAA,OAAO,CAAA,CAAE,QAAA,CAAS,CAAA,mBAAA,EAAsB,YAAY,CAAA,CAAE,CAAA;AAAA,IACxD;AAAA,EACF,SAAS,KAAA,EAAO;AACd,IAAA,OAAA,CAAQ,KAAA,CAAM,8BAA8B,KAAK,CAAA;AACjD,IAAA,MAAM,MAAA,GAAS,CAAA,CAAE,GAAA,CAAI,MAAA,CAAO,YAAY,CAAA,KAAM,MAAA;AAE9C,IAAA,IAAI,MAAA,EAAQ;AACV,MAAA,OAAO,EAAE,IAAA,CAAKA,SAAAA;AAAA;AAAA;AAAA;AAAA,MAAA,CAIb,CAAA;AAAA,IACH,CAAA,MAAO;AACL,MAAA,OAAO,CAAA,CAAE,SAAS,wBAAwB,CAAA;AAAA,IAC5C;AAAA,EACF;AACF,CAAC,CAAA;AAGD,sBAAA,CAAuB,GAAA,CAAI,MAAA,EAAQ,OAAO,CAAA,KAAM;AAC9C,EAAA,MAAM,EAAA,GAAK,EAAE,GAAA,CAAI,EAAA;AACjB,EAAA,IAAI;AACF,IAAA,MAAM,EAAA,GAAK,CAAA,CAAE,GAAA,CAAI,KAAA,CAAM,IAAI,CAAA;AAC3B,IAAA,MAAM,IAAA,GAAO,CAAA,CAAE,GAAA,CAAI,MAAM,CAAA;AAEzB,IAAA,MAAM,IAAA,GAAO,EAAA,CAAG,OAAA,CAAQ,wCAAwC,CAAA;AAChE,IAAA,MAAM,aAAa,MAAM,IAAA,CAAK,IAAA,CAAK,EAAE,EAAE,KAAA,EAAM;AAE7C,IAAA,IAAI,CAAC,UAAA,EAAY;AAEf,MAAA,MAAM,CAACkC,cAAAA,EAAeC,YAAAA,EAAaC,gBAAe,CAAA,GAAI,MAAM,QAAQ,GAAA,CAAI;AAAA,QACtE/C,eAAAA,CAAe,IAAI,gBAAgB,CAAA;AAAA,QACnCA,eAAAA,CAAe,IAAI,cAAc,CAAA;AAAA,QACjCA,eAAAA,CAAe,IAAI,UAAU;AAAA,OAC9B,CAAA;AAED,MAAA,MAAMwB,SAAAA,GAA+B;AAAA,QACnC,MAAA,EAAQ,IAAA;AAAA,QACR,KAAA,EAAO,uBAAA;AAAA,QACP,MAAM,IAAA,GAAO;AAAA,UACX,MAAM,IAAA,CAAK,KAAA;AAAA,UACX,OAAO,IAAA,CAAK,KAAA;AAAA,UACZ,MAAM,IAAA,CAAK;AAAA,SACb,GAAI,KAAA,CAAA;AAAA,QACJ,OAAA,EAAS,CAAA,CAAE,GAAA,CAAI,YAAY,CAAA;AAAA,QAC3B,aAAA,EAAe;AAAA,UACb,OAAA,EAASqB,cAAAA;AAAA,UACT,KAAA,EAAOC,YAAAA;AAAA,UACP,OAAA,EAASC;AAAA;AACX,OACF;AACA,MAAA,OAAO,CAAA,CAAE,IAAA,CAAK,wBAAA,CAAyBvB,SAAQ,CAAC,CAAA;AAAA,IAClD;AAGA,IAAA,IAAI,SAA4B,EAAC;AAGjC,IAAA,IAAI,WAAW,MAAA,EAAQ;AACrB,MAAA,IAAI;AACF,QAAA,MAAM,MAAA,GAAS,OAAO,UAAA,CAAW,MAAA,KAAW,QAAA,GAAW,KAAK,KAAA,CAAM,UAAA,CAAW,MAAM,CAAA,GAAI,UAAA,CAAW,MAAA;AAClG,QAAA,IAAI,MAAA,IAAU,OAAO,UAAA,EAAY;AAE/B,UAAA,IAAI,UAAA,GAAa,CAAA;AACjB,UAAA,MAAA,GAAS,MAAA,CAAO,OAAA,CAAQ,MAAA,CAAO,UAAU,CAAA,CAAE,IAAI,CAAC,CAAC,SAAA,EAAW,WAAW,CAAA,MAAsB;AAAA,YAC3F,EAAA,EAAI,UAAU,SAAS,CAAA,CAAA;AAAA,YACvB,UAAA,EAAY,SAAA;AAAA,YACZ,UAAA,EAAY,YAAY,IAAA,IAAQ,QAAA;AAAA,YAChC,WAAA,EAAa,YAAY,KAAA,IAAS,SAAA;AAAA,YAClC,aAAA,EAAe,WAAA;AAAA,YACf,WAAA,EAAa,UAAA,EAAA;AAAA,YACb,WAAA,EAAa,YAAY,QAAA,KAAa,IAAA,IAAS,OAAO,QAAA,IAAY,MAAA,CAAO,QAAA,CAAS,QAAA,CAAS,SAAS,CAAA;AAAA,YACpG,aAAA,EAAe,WAAA,CAAY,UAAA,KAAe,IAAA,IAAQ;AAAA,WACpD,CAAE,CAAA;AAAA,QACJ;AAAA,MACF,SAAS,CAAA,EAAG;AACV,QAAA,OAAA,CAAQ,KAAA,CAAM,oCAAoC,CAAC,CAAA;AAAA,MACrD;AAAA,IACF;AAGA,IAAA,IAAI,MAAA,CAAO,WAAW,CAAA,EAAG;AACvB,MAAA,MAAM,UAAA,GAAa,GAAG,OAAA,CAAQ;AAAA;AAAA;AAAA;AAAA,MAAA,CAI7B,CAAA;AACD,MAAA,MAAM,EAAE,SAAS,aAAA,EAAc,GAAI,MAAM,UAAA,CAAW,IAAA,CAAK,EAAE,CAAA,CAAE,GAAA,EAAI;AACjE,MAAA,MAAA,GAAA,CAAU,aAAA,IAAiB,EAAC,EAAG,GAAA,CAAI,CAAC,GAAA,KAAa;AAC/C,QAAA,IAAI,eAAe,EAAC;AACpB,QAAA,IAAI,IAAI,aAAA,EAAe;AACrB,UAAA,IAAI;AACF,YAAA,YAAA,GAAe,OAAO,IAAI,aAAA,KAAkB,QAAA,GAAW,KAAK,KAAA,CAAM,GAAA,CAAI,aAAa,CAAA,GAAI,GAAA,CAAI,aAAA;AAAA,UAC7F,SAAS,CAAA,EAAG;AACV,YAAA,OAAA,CAAQ,KAAA,CAAM,wCAAA,EAA0C,GAAA,CAAI,UAAA,EAAY,CAAC,CAAA;AACzE,YAAA,YAAA,GAAe,EAAC;AAAA,UAClB;AAAA,QACF;AACA,QAAA,OAAO;AAAA,UACL,IAAI,GAAA,CAAI,EAAA;AAAA,UACR,YAAY,GAAA,CAAI,UAAA;AAAA,UAChB,YAAY,GAAA,CAAI,UAAA;AAAA,UAChB,aAAa,GAAA,CAAI,WAAA;AAAA,UACjB,aAAA,EAAe,YAAA;AAAA,UACf,aAAa,GAAA,CAAI,WAAA;AAAA,UACjB,WAAA,EAAa,IAAI,WAAA,KAAgB,CAAA;AAAA,UACjC,aAAA,EAAe,IAAI,aAAA,KAAkB;AAAA,SACvC;AAAA,MACF,CAAC,CAAA;AAAA,IACH;AAGA,IAAA,MAAM,CAAC,aAAA,EAAe,WAAA,EAAa,eAAe,CAAA,GAAI,MAAM,QAAQ,GAAA,CAAI;AAAA,MACtExB,eAAAA,CAAe,IAAI,gBAAgB,CAAA;AAAA,MACnCA,eAAAA,CAAe,IAAI,cAAc,CAAA;AAAA,MACjCA,eAAAA,CAAe,IAAI,UAAU;AAAA,KAC9B,CAAA;AAED,IAAA,OAAA,CAAQ,IAAI,2CAAA,EAA6C;AAAA,MACvD,OAAA,EAAS,aAAA;AAAA,MACT,KAAA,EAAO,WAAA;AAAA,MACP,OAAA,EAAS;AAAA,KACV,CAAA;AAED,IAAA,MAAM,QAAA,GAA+B;AAAA,MACnC,IAAI,UAAA,CAAW,EAAA;AAAA,MACf,MAAM,UAAA,CAAW,IAAA;AAAA,MACjB,cAAc,UAAA,CAAW,YAAA;AAAA,MACzB,aAAa,UAAA,CAAW,WAAA;AAAA,MACxB,MAAA;AAAA,MACA,OAAA,EAAS,WAAW,OAAA,KAAY,CAAA;AAAA,MAChC,MAAA,EAAQ,IAAA;AAAA,MACR,MAAM,IAAA,GAAO;AAAA,QACX,MAAM,IAAA,CAAK,KAAA;AAAA,QACX,OAAO,IAAA,CAAK,KAAA;AAAA,QACZ,MAAM,IAAA,CAAK;AAAA,OACb,GAAI,KAAA,CAAA;AAAA,MACJ,OAAA,EAAS,CAAA,CAAE,GAAA,CAAI,YAAY,CAAA;AAAA,MAC3B,aAAA,EAAe;AAAA,QACb,OAAA,EAAS,aAAA;AAAA,QACT,KAAA,EAAO,WAAA;AAAA,QACP,OAAA,EAAS;AAAA;AACX,KACF;AAEA,IAAA,OAAO,CAAA,CAAE,IAAA,CAAK,wBAAA,CAAyB,QAAQ,CAAC,CAAA;AAAA,EAClD,SAAS,KAAA,EAAO;AACd,IAAA,OAAA,CAAQ,KAAA,CAAM,8BAA8B,KAAK,CAAA;AACjD,IAAA,MAAM,IAAA,GAAO,CAAA,CAAE,GAAA,CAAI,MAAM,CAAA;AAGzB,IAAA,MAAM,CAAC,aAAA,EAAe,WAAA,EAAa,eAAe,CAAA,GAAI,MAAM,QAAQ,GAAA,CAAI;AAAA,MACtEA,eAAAA,CAAe,IAAI,gBAAgB,CAAA;AAAA,MACnCA,eAAAA,CAAe,IAAI,cAAc,CAAA;AAAA,MACjCA,eAAAA,CAAe,IAAI,UAAU;AAAA,KAC9B,CAAA;AAED,IAAA,MAAM,QAAA,GAA+B;AAAA,MACnC,MAAA,EAAQ,IAAA;AAAA,MACR,KAAA,EAAO,4BAAA;AAAA,MACP,MAAM,IAAA,GAAO;AAAA,QACX,MAAM,IAAA,CAAK,KAAA;AAAA,QACX,OAAO,IAAA,CAAK,KAAA;AAAA,QACZ,MAAM,IAAA,CAAK;AAAA,OACb,GAAI,MAAA;AAAA,MACJ,OAAA,EAAS,CAAA,CAAE,GAAA,CAAI,YAAY,CAAA;AAAA,MAC3B,aAAA,EAAe;AAAA,QACb,OAAA,EAAS,aAAA;AAAA,QACT,KAAA,EAAO,WAAA;AAAA,QACP,OAAA,EAAS;AAAA;AACX,KACF;AACA,IAAA,OAAO,CAAA,CAAE,IAAA,CAAK,wBAAA,CAAyB,QAAQ,CAAC,CAAA;AAAA,EAClD;AACF,CAAC,CAAA;AAGD,sBAAA,CAAuB,GAAA,CAAI,MAAA,EAAQ,OAAO,CAAA,KAAM;AAC9C,EAAA,IAAI;AACF,IAAA,MAAM,EAAA,GAAK,CAAA,CAAE,GAAA,CAAI,KAAA,CAAM,IAAI,CAAA;AAC3B,IAAA,MAAM,QAAA,GAAW,MAAM,CAAA,CAAE,GAAA,CAAI,QAAA,EAAS;AACtC,IAAA,MAAM,WAAA,GAAc,QAAA,CAAS,GAAA,CAAI,aAAa,CAAA;AAC9C,IAAA,MAAM,WAAA,GAAc,QAAA,CAAS,GAAA,CAAI,aAAa,CAAA;AAE9C,IAAA,IAAI,CAAC,WAAA,EAAa;AAChB,MAAA,OAAO,EAAE,IAAA,CAAKW,SAAAA;AAAA;AAAA;AAAA;AAAA,MAAA,CAIb,CAAA;AAAA,IACH;AAEA,IAAA,MAAM,EAAA,GAAK,EAAE,GAAA,CAAI,EAAA;AAEjB,IAAA,MAAM,UAAA,GAAa,GAAG,OAAA,CAAQ;AAAA;AAAA;AAAA;AAAA,IAAA,CAI7B,CAAA;AAED,IAAA,MAAM,UAAA,CAAW,IAAA,CAAK,WAAA,EAAa,WAAA,IAAe,IAAA,EAAM,KAAK,GAAA,EAAI,EAAG,EAAE,CAAA,CAAE,GAAA,EAAI;AAE5E,IAAA,OAAO,EAAE,IAAA,CAAKA,SAAAA;AAAA;AAAA;AAAA;AAAA,IAAA,CAIb,CAAA;AAAA,EACH,SAAS,KAAA,EAAO;AACd,IAAA,OAAA,CAAQ,KAAA,CAAM,8BAA8B,KAAK,CAAA;AACjD,IAAA,OAAO,EAAE,IAAA,CAAKA,SAAAA;AAAA;AAAA;AAAA;AAAA,IAAA,CAIb,CAAA;AAAA,EACH;AACF,CAAC,CAAA;AAGD,sBAAA,CAAuB,MAAA,CAAO,MAAA,EAAQ,OAAO,CAAA,KAAM;AACjD,EAAA,IAAI;AACF,IAAA,MAAM,EAAA,GAAK,CAAA,CAAE,GAAA,CAAI,KAAA,CAAM,IAAI,CAAA;AAC3B,IAAA,MAAM,EAAA,GAAK,EAAE,GAAA,CAAI,EAAA;AAGjB,IAAA,MAAM,WAAA,GAAc,EAAA,CAAG,OAAA,CAAQ,+DAA+D,CAAA;AAC9F,IAAA,MAAM,gBAAgB,MAAM,WAAA,CAAY,IAAA,CAAK,EAAE,EAAE,KAAA,EAAM;AAEvD,IAAA,IAAI,aAAA,IAAiB,aAAA,CAAc,KAAA,GAAQ,CAAA,EAAG;AAC5C,MAAA,OAAO,EAAE,IAAA,CAAKA,SAAAA;AAAA;AAAA,gDAAA,EAE8B,cAAc,KAAK,CAAA;AAAA;AAAA,MAAA,CAE9D,CAAA;AAAA,IACH;AAGA,IAAA,MAAM,gBAAA,GAAmB,EAAA,CAAG,OAAA,CAAQ,oDAAoD,CAAA;AACxF,IAAA,MAAM,gBAAA,CAAiB,IAAA,CAAK,EAAE,CAAA,CAAE,GAAA,EAAI;AAGpC,IAAA,MAAM,UAAA,GAAa,EAAA,CAAG,OAAA,CAAQ,sCAAsC,CAAA;AACpE,IAAA,MAAM,UAAA,CAAW,IAAA,CAAK,EAAE,CAAA,CAAE,GAAA,EAAI;AAE9B,IAAA,OAAO,EAAE,IAAA,CAAKA,SAAAA;AAAA;AAAA;AAAA;AAAA,IAAA,CAIb,CAAA;AAAA,EACH,SAAS,KAAA,EAAO;AACd,IAAA,OAAA,CAAQ,KAAA,CAAM,8BAA8B,KAAK,CAAA;AACjD,IAAA,OAAO,EAAE,IAAA,CAAKA,SAAAA;AAAA;AAAA;AAAA;AAAA,IAAA,CAIb,CAAA;AAAA,EACH;AACF,CAAC,CAAA;AAGD,sBAAA,CAAuB,IAAA,CAAK,aAAA,EAAe,OAAO,CAAA,KAAM;AACtD,EAAA,IAAI;AACF,IAAA,MAAM,YAAA,GAAe,CAAA,CAAE,GAAA,CAAI,KAAA,CAAM,IAAI,CAAA;AACrC,IAAA,MAAM,QAAA,GAAW,MAAM,CAAA,CAAE,GAAA,CAAI,QAAA,EAAS;AACtC,IAAA,MAAM,SAAA,GAAY,QAAA,CAAS,GAAA,CAAI,YAAY,CAAA;AAC3C,IAAA,MAAM,SAAA,GAAY,QAAA,CAAS,GAAA,CAAI,YAAY,CAAA;AAC3C,IAAA,MAAM,UAAA,GAAa,QAAA,CAAS,GAAA,CAAI,aAAa,CAAA;AAC7C,IAAA,MAAM,UAAA,GAAa,QAAA,CAAS,GAAA,CAAI,aAAa,CAAA,KAAM,GAAA;AACnD,IAAA,MAAM,YAAA,GAAe,QAAA,CAAS,GAAA,CAAI,eAAe,CAAA,KAAM,GAAA;AACvD,IAAA,MAAM,YAAA,GAAe,QAAA,CAAS,GAAA,CAAI,eAAe,CAAA,IAAe,IAAA;AAEhE,IAAA,IAAI,CAAC,SAAA,IAAa,CAAC,SAAA,IAAa,CAAC,UAAA,EAAY;AAC3C,MAAA,OAAO,EAAE,IAAA,CAAK,EAAE,SAAS,KAAA,EAAO,KAAA,EAAO,6CAA6C,CAAA;AAAA,IACtF;AAGA,IAAA,IAAI,CAAC,cAAA,CAAe,IAAA,CAAK,SAAS,CAAA,EAAG;AACnC,MAAA,OAAO,EAAE,IAAA,CAAK,EAAE,SAAS,KAAA,EAAO,KAAA,EAAO,6EAA6E,CAAA;AAAA,IACtH;AAEA,IAAA,MAAM,EAAA,GAAK,EAAE,GAAA,CAAI,EAAA;AAGjB,IAAA,MAAM,YAAA,GAAe,EAAA,CAAG,OAAA,CAAQ,0EAA0E,CAAA;AAC1G,IAAA,MAAM,WAAW,MAAM,YAAA,CAAa,KAAK,YAAA,EAAc,SAAS,EAAE,KAAA,EAAM;AAExE,IAAA,IAAI,QAAA,EAAU;AACZ,MAAA,OAAO,EAAE,IAAA,CAAK,EAAE,SAAS,KAAA,EAAO,KAAA,EAAO,0CAA0C,CAAA;AAAA,IACnF;AAGA,IAAA,MAAM,SAAA,GAAY,EAAA,CAAG,OAAA,CAAQ,kFAAkF,CAAA;AAC/G,IAAA,MAAM,cAAc,MAAM,SAAA,CAAU,IAAA,CAAK,YAAY,EAAE,KAAA,EAAM;AAC7D,IAAA,MAAM,SAAA,GAAA,CAAa,WAAA,EAAa,SAAA,IAAa,CAAA,IAAK,CAAA;AAGlD,IAAA,MAAM,OAAA,GAAU,OAAO,UAAA,EAAW;AAClC,IAAA,MAAM,GAAA,GAAM,KAAK,GAAA,EAAI;AAErB,IAAA,MAAM,UAAA,GAAa,GAAG,OAAA,CAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAAA,CAM7B,CAAA;AAED,IAAA,MAAM,UAAA,CAAW,IAAA;AAAA,MACf,OAAA;AAAA,MACA,YAAA;AAAA,MACA,SAAA;AAAA,MACA,SAAA;AAAA,MACA,UAAA;AAAA,MACA,YAAA;AAAA,MACA,SAAA;AAAA,MACA,aAAa,CAAA,GAAI,CAAA;AAAA,MACjB,eAAe,CAAA,GAAI,CAAA;AAAA,MACnB,GAAA;AAAA,MACA;AAAA,MACA,GAAA,EAAI;AAEN,IAAA,OAAO,EAAE,IAAA,CAAK,EAAE,OAAA,EAAS,IAAA,EAAM,SAAS,CAAA;AAAA,EAC1C,SAAS,KAAA,EAAO;AACd,IAAA,OAAA,CAAQ,KAAA,CAAM,uBAAuB,KAAK,CAAA;AAC1C,IAAA,OAAO,EAAE,IAAA,CAAK,EAAE,SAAS,KAAA,EAAO,KAAA,EAAO,wBAAwB,CAAA;AAAA,EACjE;AACF,CAAC,CAAA;AAGD,sBAAA,CAAuB,GAAA,CAAI,gCAAA,EAAkC,OAAO,CAAA,KAAM;AACxE,EAAA,IAAI;AACF,IAAA,MAAM,OAAA,GAAU,CAAA,CAAE,GAAA,CAAI,KAAA,CAAM,SAAS,CAAA;AACrC,IAAA,MAAM,YAAA,GAAe,CAAA,CAAE,GAAA,CAAI,KAAA,CAAM,cAAc,CAAA;AAC/C,IAAA,MAAM,QAAA,GAAW,MAAM,CAAA,CAAE,GAAA,CAAI,QAAA,EAAS;AACtC,IAAA,MAAM,UAAA,GAAa,QAAA,CAAS,GAAA,CAAI,aAAa,CAAA;AAC7C,IAAA,MAAM,SAAA,GAAY,QAAA,CAAS,GAAA,CAAI,YAAY,CAAA;AAE3C,IAAA,MAAM,gBAAA,GAAmB,QAAA,CAAS,MAAA,CAAO,aAAa,CAAA;AACtD,IAAA,MAAM,kBAAA,GAAqB,QAAA,CAAS,MAAA,CAAO,eAAe,CAAA;AAC1D,IAAA,MAAM,UAAA,GAAa,gBAAA,CAAiB,gBAAA,CAAiB,MAAA,GAAS,CAAC,CAAA,KAAM,GAAA;AACrE,IAAA,MAAM,YAAA,GAAe,kBAAA,CAAmB,kBAAA,CAAmB,MAAA,GAAS,CAAC,CAAA,KAAM,GAAA;AAC3E,IAAA,MAAM,YAAA,GAAe,QAAA,CAAS,GAAA,CAAI,eAAe,CAAA,IAAe,IAAA;AAGhE,IAAA,OAAA,CAAQ,GAAA,CAAI,4BAA4B,OAAO,CAAA;AAC/C,IAAA,OAAA,CAAQ,IAAI,oCAAA,EAAsC;AAAA,MAChD,WAAA,EAAa,UAAA;AAAA,MACb,UAAA,EAAY,SAAA;AAAA,MACZ,WAAA,EAAa,QAAA,CAAS,GAAA,CAAI,aAAa,CAAA;AAAA,MACvC,aAAA,EAAe,QAAA,CAAS,GAAA,CAAI,eAAe,CAAA;AAAA,MAC3C,aAAA,EAAe;AAAA,KAChB,CAAA;AAED,IAAA,IAAI,CAAC,UAAA,EAAY;AACf,MAAA,OAAO,EAAE,IAAA,CAAK,EAAE,SAAS,KAAA,EAAO,KAAA,EAAO,4BAA4B,CAAA;AAAA,IACrE;AAEA,IAAA,MAAM,EAAA,GAAK,EAAE,GAAA,CAAI,EAAA;AAGjB,IAAA,IAAI,OAAA,CAAQ,UAAA,CAAW,SAAS,CAAA,EAAG;AAGjC,MAAA,MAAM,SAAA,GAAY,OAAA,CAAQ,OAAA,CAAQ,SAAA,EAAW,EAAE,CAAA;AAE/C,MAAA,OAAA,CAAQ,GAAA,CAAI,yCAAyC,SAAS,CAAA;AAG9D,MAAA,MAAM,iBAAA,GAAoB,EAAA,CAAG,OAAA,CAAQ,wCAAwC,CAAA;AAC7E,MAAA,MAAM,aAAa,MAAM,iBAAA,CAAkB,IAAA,CAAK,YAAY,EAAE,KAAA,EAAM;AAEpE,MAAA,IAAI,CAAC,UAAA,EAAY;AACf,QAAA,OAAO,EAAE,IAAA,CAAK,EAAE,SAAS,KAAA,EAAO,KAAA,EAAO,yBAAyB,CAAA;AAAA,MAClE;AAGA,MAAA,IAAI,MAAA,GAAS,OAAO,UAAA,CAAW,MAAA,KAAW,QAAA,GAAW,KAAK,KAAA,CAAM,UAAA,CAAW,MAAM,CAAA,GAAI,UAAA,CAAW,MAAA;AAChG,MAAA,IAAI,CAAC,MAAA,EAAQ;AACX,QAAA,MAAA,GAAS,EAAE,MAAM,QAAA,EAAU,UAAA,EAAY,EAAC,EAAG,QAAA,EAAU,EAAC,EAAE;AAAA,MAC1D;AACA,MAAA,IAAI,CAAC,OAAO,UAAA,EAAY;AACtB,QAAA,MAAA,CAAO,aAAa,EAAC;AAAA,MACvB;AACA,MAAA,IAAI,CAAC,OAAO,QAAA,EAAU;AACpB,QAAA,MAAA,CAAO,WAAW,EAAC;AAAA,MACrB;AAGA,MAAA,IAAI,MAAA,CAAO,UAAA,CAAW,SAAS,CAAA,EAAG;AAEhC,QAAA,MAAM,kBAAA,GAA0B;AAAA,UAC9B,GAAG,MAAA,CAAO,UAAA,CAAW,SAAS,CAAA;AAAA,UAC9B,IAAA,EAAM,SAAA;AAAA,UACN,KAAA,EAAO,UAAA;AAAA,UACP,UAAA,EAAY;AAAA,SACd;AAIA,QAAA,IAAI,UAAA,EAAY;AACd,UAAA,kBAAA,CAAmB,QAAA,GAAW,IAAA;AAAA,QAChC,CAAA,MAAO;AACL,UAAA,OAAO,kBAAA,CAAmB,QAAA;AAAA,QAC5B;AAEA,QAAA,MAAA,CAAO,UAAA,CAAW,SAAS,CAAA,GAAI,kBAAA;AAG/B,QAAA,MAAM,aAAA,GAAgB,MAAA,CAAO,QAAA,CAAS,OAAA,CAAQ,SAAS,CAAA;AACvD,QAAA,OAAA,CAAQ,IAAI,yCAAA,EAA2C;AAAA,UACrD,SAAA;AAAA,UACA,UAAA;AAAA,UACA,sBAAsB,MAAA,CAAO,QAAA;AAAA,UAC7B;AAAA,SACD,CAAA;AAED,QAAA,IAAI,UAAA,IAAc,kBAAkB,CAAA,CAAA,EAAI;AAEtC,UAAA,MAAA,CAAO,QAAA,CAAS,KAAK,SAAS,CAAA;AAC9B,UAAA,OAAA,CAAQ,IAAI,8CAA8C,CAAA;AAAA,QAC5D,CAAA,MAAA,IAAW,CAAC,UAAA,IAAc,aAAA,KAAkB,CAAA,CAAA,EAAI;AAE9C,UAAA,MAAA,CAAO,QAAA,CAAS,MAAA,CAAO,aAAA,EAAe,CAAC,CAAA;AACvC,UAAA,OAAA,CAAQ,IAAI,kDAAkD,CAAA;AAAA,QAChE;AAEA,QAAA,OAAA,CAAQ,GAAA,CAAI,sCAAA,EAAwC,MAAA,CAAO,QAAQ,CAAA;AACnE,QAAA,OAAA,CAAQ,GAAA,CAAI,oCAAA,EAAsC,MAAA,CAAO,UAAA,CAAW,SAAS,CAAC,CAAA;AAAA,MAChF;AAGA,MAAA,MAAM,oBAAA,GAAuB,GAAG,OAAA,CAAQ;AAAA;AAAA;AAAA;AAAA,MAAA,CAIvC,CAAA;AAED,MAAA,MAAMqC,OAAAA,GAAS,MAAM,oBAAA,CAAqB,IAAA,CAAK,IAAA,CAAK,SAAA,CAAU,MAAM,CAAA,EAAG,IAAA,CAAK,GAAA,EAAI,EAAG,YAAY,EAAE,GAAA,EAAI;AAErG,MAAA,OAAA,CAAQ,IAAI,sCAAA,EAAwC;AAAA,QAClD,SAASA,OAAAA,CAAO,OAAA;AAAA,QAChB,OAAA,EAASA,QAAO,IAAA,EAAM;AAAA,OACvB,CAAA;AAED,MAAA,OAAO,CAAA,CAAE,IAAA,CAAK,EAAE,OAAA,EAAS,MAAM,CAAA;AAAA,IACjC;AAGA,IAAA,MAAM,UAAA,GAAa,GAAG,OAAA,CAAQ;AAAA;AAAA;AAAA;AAAA,IAAA,CAI7B,CAAA;AAED,IAAA,MAAM,SAAS,MAAM,UAAA,CAAW,KAAK,UAAA,EAAY,SAAA,EAAW,cAAc,UAAA,GAAa,CAAA,GAAI,CAAA,EAAG,YAAA,GAAe,IAAI,CAAA,EAAG,IAAA,CAAK,KAAI,EAAG,OAAO,EAAE,GAAA,EAAI;AAE7I,IAAA,OAAA,CAAQ,IAAI,+BAAA,EAAiC;AAAA,MAC3C,SAAS,MAAA,CAAO,OAAA;AAAA,MAChB,MAAM,MAAA,CAAO,IAAA;AAAA,MACb,OAAA,EAAS,OAAO,IAAA,EAAM,OAAA;AAAA,MACtB,WAAA,EAAa,OAAO,IAAA,EAAM;AAAA,KAC3B,CAAA;AAGD,IAAA,MAAM,UAAA,GAAa,EAAA,CAAG,OAAA,CAAQ,2CAA2C,CAAA;AACzE,IAAA,MAAM,eAAe,MAAM,UAAA,CAAW,IAAA,CAAK,OAAO,EAAE,KAAA,EAAM;AAC1D,IAAA,OAAA,CAAQ,GAAA,CAAI,qDAAqD,YAAY,CAAA;AAE7E,IAAA,OAAA,CAAQ,GAAA,CAAI,wDAAwD,SAAS,CAAA;AAE7E,IAAA,OAAO,CAAA,CAAE,IAAA,CAAK,EAAE,OAAA,EAAS,MAAM,CAAA;AAAA,EACjC,SAAS,KAAA,EAAO;AACd,IAAA,OAAA,CAAQ,KAAA,CAAM,yBAAyB,KAAK,CAAA;AAC5C,IAAA,OAAO,EAAE,IAAA,CAAK,EAAE,SAAS,KAAA,EAAO,KAAA,EAAO,2BAA2B,CAAA;AAAA,EACpE;AACF,CAAC,CAAA;AAGD,sBAAA,CAAuB,MAAA,CAAO,gCAAA,EAAkC,OAAO,CAAA,KAAM;AAC3E,EAAA,IAAI;AACF,IAAA,MAAM,OAAA,GAAU,CAAA,CAAE,GAAA,CAAI,KAAA,CAAM,SAAS,CAAA;AACrC,IAAA,MAAM,EAAA,GAAK,EAAE,GAAA,CAAI,EAAA;AAEjB,IAAA,MAAM,UAAA,GAAa,EAAA,CAAG,OAAA,CAAQ,yCAAyC,CAAA;AACvE,IAAA,MAAM,UAAA,CAAW,IAAA,CAAK,OAAO,CAAA,CAAE,GAAA,EAAI;AAEnC,IAAA,OAAO,CAAA,CAAE,IAAA,CAAK,EAAE,OAAA,EAAS,MAAM,CAAA;AAAA,EACjC,SAAS,KAAA,EAAO;AACd,IAAA,OAAA,CAAQ,KAAA,CAAM,yBAAyB,KAAK,CAAA;AAC5C,IAAA,OAAO,EAAE,IAAA,CAAK,EAAE,SAAS,KAAA,EAAO,KAAA,EAAO,2BAA2B,CAAA;AAAA,EACpE;AACF,CAAC,CAAA;AAGD,sBAAA,CAAuB,IAAA,CAAK,+BAAA,EAAiC,OAAO,CAAA,KAAM;AACxE,EAAA,IAAI;AACF,IAAA,MAAM,IAAA,GAAO,MAAM,CAAA,CAAE,GAAA,CAAI,IAAA,EAAK;AAC9B,IAAA,MAAM,WAAW,IAAA,CAAK,QAAA;AAEtB,IAAA,IAAI,CAAC,KAAA,CAAM,OAAA,CAAQ,QAAQ,CAAA,EAAG;AAC5B,MAAA,OAAO,EAAE,IAAA,CAAK,EAAE,SAAS,KAAA,EAAO,KAAA,EAAO,6BAA6B,CAAA;AAAA,IACtE;AAEA,IAAA,MAAM,EAAA,GAAK,EAAE,GAAA,CAAI,EAAA;AAGjB,IAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,QAAA,CAAS,QAAQ,CAAA,EAAA,EAAK;AACxC,MAAA,MAAM,UAAA,GAAa,EAAA,CAAG,OAAA,CAAQ,wEAAwE,CAAA;AACtG,MAAA,MAAM,UAAA,CAAW,IAAA,CAAK,CAAA,GAAI,CAAA,EAAG,IAAA,CAAK,GAAA,EAAI,EAAG,QAAA,CAAS,CAAC,CAAC,CAAA,CAAE,GAAA,EAAI;AAAA,IAC5D;AAEA,IAAA,OAAO,CAAA,CAAE,IAAA,CAAK,EAAE,OAAA,EAAS,MAAM,CAAA;AAAA,EACjC,SAAS,KAAA,EAAO;AACd,IAAA,OAAA,CAAQ,KAAA,CAAM,4BAA4B,KAAK,CAAA;AAC/C,IAAA,OAAO,EAAE,IAAA,CAAK,EAAE,SAAS,KAAA,EAAO,KAAA,EAAO,6BAA6B,CAAA;AAAA,EACtE;AACF,CAAC,CAAA;;;ACv1BDlC,qDAAA,EAAA;AA8FO,SAAS,mBAAmB,IAAA,EAAgC;AACjE,EAAA,MAAM,SAAA,GAAY,KAAK,SAAA,IAAa,SAAA;AAEpC,EAAA,MAAM,WAAA,GAAc;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA,YAAA,EAcR,eAAA,CAAgB,SAAA,EAAW,SAAA,EAAW,sgBAAA,EAAwgB,SAAS,CAAC;AAAA,YAAA,EACxjB,eAAA,CAAgB,YAAA,EAAc,YAAA,EAAc,mIAAA,EAAqI,SAAS,CAAC;AAAA,YAAA,EAC3L,eAAA,CAAgB,UAAA,EAAY,UAAA,EAAY,sGAAA,EAAwG,SAAS,CAAC;AAAA,YAAA,EAC1J,eAAA,CAAgB,eAAA,EAAiB,eAAA,EAAiB,+LAAA,EAAiM,SAAS,CAAC;AAAA,YAAA,EAC7P,eAAA,CAAgB,SAAA,EAAW,SAAA,EAAW,uFAAA,EAAyF,SAAS,CAAC;AAAA,YAAA,EACzI,eAAA,CAAgB,YAAA,EAAc,YAAA,EAAc,gJAAA,EAAkJ,SAAS,CAAC;AAAA,YAAA,EACxM,eAAA,CAAgB,gBAAA,EAAkB,gBAAA,EAAkB,0JAAA,EAA4J,SAAS,CAAC;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA,UAAA,EAQ5N,gBAAA,CAAiB,SAAA,EAAW,IAAA,CAAK,QAAQ,CAAC;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA,0BAAA,EAO1B,SAAS,CAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA,IAAA,EAmU/BG,yBAAAA,CAAyB;AAAA,IACzB,EAAA,EAAI,w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","file":"chunk-CSEI667V.cjs","sourcesContent":["/**\n * Schema Definitions\n *\n * Placeholder for schema definitions - to be populated as needed\n */\n\nexport interface SchemaDefinition {\n name: string\n fields: any[]\n}\n\n// Empty array for now - schemas will be migrated incrementally\nexport const schemaDefinitions: SchemaDefinition[] = []\n","import { Hono } from 'hono'\nimport { requireAuth } from '../middleware'\nimport { getCacheService, CACHE_CONFIGS } from '../services'\nimport type { Bindings, Variables } from '../app'\n\nconst apiContentCrudRoutes = new Hono<{ Bindings: Bindings; Variables: Variables }>()\n\n// GET /api/content/:id - Get single content item by ID\napiContentCrudRoutes.get('/:id', async (c) => {\n try {\n const id = c.req.param('id')\n const db = c.env.DB\n\n const stmt = db.prepare('SELECT * FROM content WHERE id = ?')\n const content = await stmt.bind(id).first()\n\n if (!content) {\n return c.json({ error: 'Content not found' }, 404)\n }\n\n const transformedContent = {\n id: (content as any).id,\n title: (content as any).title,\n slug: (content as any).slug,\n status: (content as any).status,\n collectionId: (content as any).collection_id,\n data: (content as any).data ? JSON.parse((content as any).data) : {},\n created_at: (content as any).created_at,\n updated_at: (content as any).updated_at\n }\n\n return c.json({ data: transformedContent })\n } catch (error) {\n console.error('Error fetching content:', error)\n return c.json({\n error: 'Failed to fetch content',\n details: error instanceof Error ? error.message : String(error)\n }, 500)\n }\n})\n\n// POST /api/content - Create new content (requires authentication)\napiContentCrudRoutes.post('/', requireAuth(), async (c) => {\n try {\n const db = c.env.DB\n const user = c.get('user')\n const body = await c.req.json()\n\n const { collectionId, title, slug, status, data } = body\n\n // Validate required fields\n if (!collectionId) {\n return c.json({ error: 'collectionId is required' }, 400)\n }\n\n if (!title) {\n return c.json({ error: 'title is required' }, 400)\n }\n\n // Generate slug from title if not provided\n let finalSlug = slug || title\n finalSlug = finalSlug.toLowerCase()\n .replace(/[^a-z0-9\\s-]/g, '')\n .replace(/\\s+/g, '-')\n .replace(/-+/g, '-')\n .trim()\n\n // Check for duplicate slug within the same collection\n const duplicateCheck = db.prepare(\n 'SELECT id FROM content WHERE collection_id = ? AND slug = ?'\n )\n const existing = await duplicateCheck.bind(collectionId, finalSlug).first()\n\n if (existing) {\n return c.json({ error: 'A content item with this slug already exists in this collection' }, 409)\n }\n\n // Create new content\n const contentId = crypto.randomUUID()\n const now = Date.now()\n\n const insertStmt = db.prepare(`\n INSERT INTO content (\n id, collection_id, slug, title, data, status,\n author_id, created_at, updated_at\n )\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)\n `)\n\n await insertStmt.bind(\n contentId,\n collectionId,\n finalSlug,\n title,\n JSON.stringify(data || {}),\n status || 'draft',\n user?.userId || 'system',\n now,\n now\n ).run()\n\n // Invalidate cache\n const cache = getCacheService(CACHE_CONFIGS.api!)\n await cache.invalidate(`content:list:${collectionId}:*`)\n await cache.invalidate('content-filtered:*')\n\n // Get the created content\n const getStmt = db.prepare('SELECT * FROM content WHERE id = ?')\n const createdContent = await getStmt.bind(contentId).first() as any\n\n return c.json({\n data: {\n id: createdContent.id,\n title: createdContent.title,\n slug: createdContent.slug,\n status: createdContent.status,\n collectionId: createdContent.collection_id,\n data: createdContent.data ? JSON.parse(createdContent.data) : {},\n created_at: createdContent.created_at,\n updated_at: createdContent.updated_at\n }\n }, 201)\n } catch (error) {\n console.error('Error creating content:', error)\n return c.json({\n error: 'Failed to create content',\n details: error instanceof Error ? error.message : String(error)\n }, 500)\n }\n})\n\n// PUT /api/content/:id - Update content (requires authentication)\napiContentCrudRoutes.put('/:id', requireAuth(), async (c) => {\n try {\n const id = c.req.param('id')\n const db = c.env.DB\n const body = await c.req.json()\n\n // Check if content exists\n const existingStmt = db.prepare('SELECT * FROM content WHERE id = ?')\n const existing = await existingStmt.bind(id).first() as any\n\n if (!existing) {\n return c.json({ error: 'Content not found' }, 404)\n }\n\n // Build update fields dynamically\n const updates: string[] = []\n const params: any[] = []\n\n if (body.title !== undefined) {\n updates.push('title = ?')\n params.push(body.title)\n }\n\n if (body.slug !== undefined) {\n let finalSlug = body.slug.toLowerCase()\n .replace(/[^a-z0-9\\s-]/g, '')\n .replace(/\\s+/g, '-')\n .replace(/-+/g, '-')\n .trim()\n updates.push('slug = ?')\n params.push(finalSlug)\n }\n\n if (body.status !== undefined) {\n updates.push('status = ?')\n params.push(body.status)\n }\n\n if (body.data !== undefined) {\n updates.push('data = ?')\n params.push(JSON.stringify(body.data))\n }\n\n // Always update updated_at\n const now = Date.now()\n updates.push('updated_at = ?')\n params.push(now)\n\n // Add id to params for WHERE clause\n params.push(id)\n\n // Execute update\n const updateStmt = db.prepare(`\n UPDATE content SET ${updates.join(', ')}\n WHERE id = ?\n `)\n\n await updateStmt.bind(...params).run()\n\n // Invalidate cache\n const cache = getCacheService(CACHE_CONFIGS.api!)\n await cache.delete(cache.generateKey('content', id))\n await cache.invalidate(`content:list:${existing.collection_id}:*`)\n await cache.invalidate('content-filtered:*')\n\n // Get updated content\n const getStmt = db.prepare('SELECT * FROM content WHERE id = ?')\n const updatedContent = await getStmt.bind(id).first() as any\n\n return c.json({\n data: {\n id: updatedContent.id,\n title: updatedContent.title,\n slug: updatedContent.slug,\n status: updatedContent.status,\n collectionId: updatedContent.collection_id,\n data: updatedContent.data ? JSON.parse(updatedContent.data) : {},\n created_at: updatedContent.created_at,\n updated_at: updatedContent.updated_at\n }\n })\n } catch (error) {\n console.error('Error updating content:', error)\n return c.json({\n error: 'Failed to update content',\n details: error instanceof Error ? error.message : String(error)\n }, 500)\n }\n})\n\n// DELETE /api/content/:id - Delete content (requires authentication)\napiContentCrudRoutes.delete('/:id', requireAuth(), async (c) => {\n try {\n const id = c.req.param('id')\n const db = c.env.DB\n\n // Check if content exists\n const existingStmt = db.prepare('SELECT collection_id FROM content WHERE id = ?')\n const existing = await existingStmt.bind(id).first() as any\n\n if (!existing) {\n return c.json({ error: 'Content not found' }, 404)\n }\n\n // Delete the content (hard delete for API, soft delete happens in admin routes)\n const deleteStmt = db.prepare('DELETE FROM content WHERE id = ?')\n await deleteStmt.bind(id).run()\n\n // Invalidate cache\n const cache = getCacheService(CACHE_CONFIGS.api!)\n await cache.delete(cache.generateKey('content', id))\n await cache.invalidate(`content:list:${existing.collection_id}:*`)\n await cache.invalidate('content-filtered:*')\n\n return c.json({ success: true })\n } catch (error) {\n console.error('Error deleting content:', error)\n return c.json({\n error: 'Failed to delete content',\n details: error instanceof Error ? error.message : String(error)\n }, 500)\n }\n})\n\nexport default apiContentCrudRoutes\n","import { Hono } from 'hono'\nimport { cors } from 'hono/cors'\nimport { schemaDefinitions } from '../schemas'\nimport { getCacheService, CACHE_CONFIGS } from '../services'\nimport { QueryFilterBuilder, QueryFilter } from '../utils'\nimport { isPluginActive } from '../middleware'\nimport apiContentCrudRoutes from './api-content-crud'\nimport type { Bindings, Variables as AppVariables } from '../app'\n\n// Extend Variables with API-specific fields\ninterface Variables extends AppVariables {\n startTime: number\n cacheEnabled?: boolean\n}\n\nconst apiRoutes = new Hono<{ Bindings: Bindings; Variables: Variables }>()\n\n// Add timing middleware\napiRoutes.use('*', async (c, next) => {\n const startTime = Date.now()\n c.set('startTime', startTime)\n await next()\n const totalTime = Date.now() - startTime\n c.header('X-Response-Time', `${totalTime}ms`)\n})\n\n// Check if cache plugin is active\napiRoutes.use('*', async (c, next) => {\n const cacheEnabled = await isPluginActive(c.env.DB, 'core-cache')\n c.set('cacheEnabled', cacheEnabled)\n await next()\n})\n\n// Add CORS middleware\napiRoutes.use('*', cors({\n origin: '*',\n allowMethods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],\n allowHeaders: ['Content-Type', 'Authorization']\n}))\n\n// Helper function to add timing metadata\nfunction addTimingMeta(c: any, meta: any = {}, executionStartTime?: number) {\n const totalTime = Date.now() - c.get('startTime')\n const executionTime = executionStartTime ? Date.now() - executionStartTime : undefined\n\n return {\n ...meta,\n timing: {\n total: totalTime,\n execution: executionTime,\n unit: 'ms'\n }\n }\n}\n\n// Root endpoint - API info\napiRoutes.get('/', (c) => {\n return c.json({\n name: 'SonicJS API',\n version: '2.0.0',\n description: 'RESTful API for SonicJS headless CMS',\n endpoints: {\n health: '/api/health',\n collections: '/api/collections',\n content: '/api/content',\n contentById: '/api/content/:id',\n collectionContent: '/api/collections/:collection/content'\n },\n documentation: '/docs'\n })\n})\n\n// Health check endpoint\napiRoutes.get('/health', (c) => {\n return c.json({\n status: 'healthy',\n timestamp: new Date().toISOString(),\n schemas: schemaDefinitions.map(s => s.name)\n })\n})\n\n// Basic collections endpoint\napiRoutes.get('/collections', async (c) => {\n const executionStart = Date.now()\n\n try {\n const db = c.env.DB\n const cacheEnabled = c.get('cacheEnabled')\n const cache = getCacheService(CACHE_CONFIGS.api!)\n const cacheKey = cache.generateKey('collections', 'all')\n\n // Use cache only if cache plugin is active\n if (cacheEnabled) {\n const cacheResult = await cache.getWithSource<any>(cacheKey)\n if (cacheResult.hit && cacheResult.data) {\n // Add cache headers\n c.header('X-Cache-Status', 'HIT')\n c.header('X-Cache-Source', cacheResult.source)\n if (cacheResult.ttl) {\n c.header('X-Cache-TTL', Math.floor(cacheResult.ttl).toString())\n }\n\n // Add cache info and timing to meta\n const dataWithMeta = {\n ...cacheResult.data,\n meta: addTimingMeta(c, {\n ...cacheResult.data.meta,\n cache: {\n hit: true,\n source: cacheResult.source,\n ttl: cacheResult.ttl ? Math.floor(cacheResult.ttl) : undefined\n }\n }, executionStart)\n }\n\n return c.json(dataWithMeta)\n }\n }\n\n // Cache miss - fetch from database\n c.header('X-Cache-Status', 'MISS')\n c.header('X-Cache-Source', 'database')\n\n const stmt = db.prepare('SELECT * FROM collections WHERE is_active = 1')\n const { results } = await stmt.all()\n\n // Parse schema and format results\n const transformedResults = results.map((row: any) => ({\n ...row,\n schema: row.schema ? JSON.parse(row.schema) : {},\n is_active: row.is_active // Keep as number (1 or 0)\n }))\n\n const responseData = {\n data: transformedResults,\n meta: addTimingMeta(c, {\n count: results.length,\n timestamp: new Date().toISOString(),\n cache: {\n hit: false,\n source: 'database'\n }\n }, executionStart)\n }\n\n // Cache the response only if cache plugin is enabled\n if (cacheEnabled) {\n await cache.set(cacheKey, responseData)\n }\n\n return c.json(responseData)\n } catch (error) {\n console.error('Error fetching collections:', error)\n return c.json({ error: 'Failed to fetch collections' }, 500)\n }\n})\n\n// Basic content endpoint with advanced filtering\napiRoutes.get('/content', async (c) => {\n const executionStart = Date.now()\n\n try {\n const db = c.env.DB\n const queryParams = c.req.query()\n\n // Handle collection parameter - convert collection name to collection_id\n if (queryParams.collection) {\n const collectionName = queryParams.collection\n const collectionStmt = db.prepare('SELECT id FROM collections WHERE name = ? AND is_active = 1')\n const collectionResult = await collectionStmt.bind(collectionName).first()\n\n if (collectionResult) {\n // Replace 'collection' param with 'collection_id' for the filter builder\n queryParams.collection_id = (collectionResult as any).id\n delete queryParams.collection\n } else {\n // Collection not found - return empty result\n return c.json({\n data: [],\n meta: addTimingMeta(c, {\n count: 0,\n timestamp: new Date().toISOString(),\n message: `Collection '${collectionName}' not found`\n }, executionStart)\n })\n }\n }\n\n // Parse filter from query parameters\n const filter: QueryFilter = QueryFilterBuilder.parseFromQuery(queryParams)\n\n // Set default limit if not provided\n if (!filter.limit) {\n filter.limit = 50\n }\n filter.limit = Math.min(filter.limit, 1000) // Max 1000\n\n // Build SQL query from filter\n const builder = new QueryFilterBuilder()\n const queryResult = builder.build('content', filter)\n\n // Check for query building errors\n if (queryResult.errors.length > 0) {\n return c.json({\n error: 'Invalid filter parameters',\n details: queryResult.errors\n }, 400)\n }\n\n // Only use cache if cache plugin is active\n const cacheEnabled = c.get('cacheEnabled')\n const cache = getCacheService(CACHE_CONFIGS.api!)\n const cacheKey = cache.generateKey('content-filtered', JSON.stringify({ filter, query: queryResult.sql }))\n\n if (cacheEnabled) {\n const cacheResult = await cache.getWithSource<any>(cacheKey)\n if (cacheResult.hit && cacheResult.data) {\n // Add cache headers\n c.header('X-Cache-Status', 'HIT')\n c.header('X-Cache-Source', cacheResult.source)\n if (cacheResult.ttl) {\n c.header('X-Cache-TTL', Math.floor(cacheResult.ttl).toString())\n }\n\n // Add cache info and timing to meta\n const dataWithMeta = {\n ...cacheResult.data,\n meta: addTimingMeta(c, {\n ...cacheResult.data.meta,\n cache: {\n hit: true,\n source: cacheResult.source,\n ttl: cacheResult.ttl ? Math.floor(cacheResult.ttl) : undefined\n }\n }, executionStart)\n }\n\n return c.json(dataWithMeta)\n }\n }\n\n // Cache miss - fetch from database\n c.header('X-Cache-Status', 'MISS')\n c.header('X-Cache-Source', 'database')\n\n // Execute query with parameters\n const stmt = db.prepare(queryResult.sql)\n const boundStmt = queryResult.params.length > 0\n ? stmt.bind(...queryResult.params)\n : stmt\n\n const { results } = await boundStmt.all()\n\n // Transform results to match API spec (camelCase)\n const transformedResults = results.map((row: any) => ({\n id: row.id,\n title: row.title,\n slug: row.slug,\n status: row.status,\n collectionId: row.collection_id,\n data: row.data ? JSON.parse(row.data) : {},\n created_at: row.created_at,\n updated_at: row.updated_at\n }))\n\n const responseData = {\n data: transformedResults,\n meta: addTimingMeta(c, {\n count: results.length,\n timestamp: new Date().toISOString(),\n filter: filter,\n query: {\n sql: queryResult.sql,\n params: queryResult.params\n },\n cache: {\n hit: false,\n source: 'database'\n }\n }, executionStart)\n }\n\n // Cache the response only if cache is enabled\n if (cacheEnabled) {\n await cache.set(cacheKey, responseData)\n }\n\n return c.json(responseData)\n } catch (error) {\n console.error('Error fetching content:', error)\n return c.json({\n error: 'Failed to fetch content',\n details: error instanceof Error ? error.message : String(error)\n }, 500)\n }\n})\n\n// Collection-specific routes with advanced filtering\napiRoutes.get('/collections/:collection/content', async (c) => {\n const executionStart = Date.now()\n\n try {\n const collection = c.req.param('collection')\n const db = c.env.DB\n const queryParams = c.req.query()\n\n // First check if collection exists\n const collectionStmt = db.prepare('SELECT * FROM collections WHERE name = ? AND is_active = 1')\n const collectionResult = await collectionStmt.bind(collection).first()\n\n if (!collectionResult) {\n return c.json({ error: 'Collection not found' }, 404)\n }\n\n // Parse filter from query parameters\n const filter: QueryFilter = QueryFilterBuilder.parseFromQuery(queryParams)\n\n // Add collection_id filter to where clause\n if (!filter.where) {\n filter.where = { and: [] }\n }\n\n if (!filter.where.and) {\n filter.where.and = []\n }\n\n // Add collection filter\n filter.where.and.push({\n field: 'collection_id',\n operator: 'equals',\n value: (collectionResult as any).id\n })\n\n // Set default limit if not provided\n if (!filter.limit) {\n filter.limit = 50\n }\n filter.limit = Math.min(filter.limit, 1000)\n\n // Build SQL query from filter\n const builder = new QueryFilterBuilder()\n const queryResult = builder.build('content', filter)\n\n // Check for query building errors\n if (queryResult.errors.length > 0) {\n return c.json({\n error: 'Invalid filter parameters',\n details: queryResult.errors\n }, 400)\n }\n\n // Generate cache key\n const cacheEnabled = c.get('cacheEnabled')\n const cache = getCacheService(CACHE_CONFIGS.api!)\n const cacheKey = cache.generateKey('collection-content-filtered', `${collection}:${JSON.stringify({ filter, query: queryResult.sql })}`)\n\n // Only check cache if plugin is enabled\n if (cacheEnabled) {\n const cacheResult = await cache.getWithSource<any>(cacheKey)\n if (cacheResult.hit && cacheResult.data) {\n // Add cache headers\n c.header('X-Cache-Status', 'HIT')\n c.header('X-Cache-Source', cacheResult.source)\n if (cacheResult.ttl) {\n c.header('X-Cache-TTL', Math.floor(cacheResult.ttl).toString())\n }\n\n // Add cache info and timing to meta\n const dataWithMeta = {\n ...cacheResult.data,\n meta: addTimingMeta(c, {\n ...cacheResult.data.meta,\n cache: {\n hit: true,\n source: cacheResult.source,\n ttl: cacheResult.ttl ? Math.floor(cacheResult.ttl) : undefined\n }\n }, executionStart)\n }\n\n return c.json(dataWithMeta)\n }\n }\n\n // Cache miss - fetch from database\n c.header('X-Cache-Status', 'MISS')\n c.header('X-Cache-Source', 'database')\n\n // Execute query with parameters\n const stmt = db.prepare(queryResult.sql)\n const boundStmt = queryResult.params.length > 0\n ? stmt.bind(...queryResult.params)\n : stmt\n\n const { results } = await boundStmt.all()\n\n // Transform results to match API spec (camelCase)\n const transformedResults = results.map((row: any) => ({\n id: row.id,\n title: row.title,\n slug: row.slug,\n status: row.status,\n collectionId: row.collection_id,\n data: row.data ? JSON.parse(row.data) : {},\n created_at: row.created_at,\n updated_at: row.updated_at\n }))\n\n const responseData = {\n data: transformedResults,\n meta: addTimingMeta(c, {\n collection: {\n ...(collectionResult as any),\n schema: (collectionResult as any).schema ? JSON.parse((collectionResult as any).schema) : {}\n },\n count: results.length,\n timestamp: new Date().toISOString(),\n filter: filter,\n query: {\n sql: queryResult.sql,\n params: queryResult.params\n },\n cache: {\n hit: false,\n source: 'database'\n }\n }, executionStart)\n }\n\n // Cache the response only if cache plugin is enabled\n if (cacheEnabled) {\n await cache.set(cacheKey, responseData)\n }\n\n return c.json(responseData)\n } catch (error) {\n console.error('Error fetching content:', error)\n return c.json({\n error: 'Failed to fetch content',\n details: error instanceof Error ? error.message : String(error)\n }, 500)\n }\n})\n\n// Mount CRUD routes for content\napiRoutes.route('/content', apiContentCrudRoutes)\n\nexport default apiRoutes\n","import { Hono } from 'hono'\nimport { z } from 'zod'\nimport { requireAuth } from '../middleware'\nimport type { Bindings, Variables } from '../app'\n\n// Helper function to generate short IDs (replacement for nanoid)\nfunction generateId(): string {\n return crypto.randomUUID().replace(/-/g, '').substring(0, 21)\n}\n\n// Helper function for emitting events (simplified for core package)\nasync function emitEvent(eventName: string, data: any) {\n console.log(`[Event] ${eventName}:`, data)\n // TODO: Implement proper event system when plugin architecture is ready\n}\n\n// File validation schema\nconst fileValidationSchema = z.object({\n name: z.string().min(1).max(255),\n type: z.string().refine(\n (type) => {\n const allowedTypes = [\n // Images\n 'image/jpeg', 'image/jpg', 'image/png', 'image/gif', 'image/webp', 'image/svg+xml',\n // Documents\n 'application/pdf', 'text/plain', 'application/msword', \n 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',\n // Videos\n 'video/mp4', 'video/webm', 'video/ogg', 'video/avi', 'video/mov',\n // Audio\n 'audio/mp3', 'audio/wav', 'audio/ogg', 'audio/m4a'\n ]\n return allowedTypes.includes(type)\n },\n { message: 'Unsupported file type' }\n ),\n size: z.number().min(1).max(50 * 1024 * 1024) // 50MB max\n})\n\nexport const apiMediaRoutes = new Hono<{ Bindings: Bindings; Variables: Variables }>()\n\n// Apply auth middleware to all routes\napiMediaRoutes.use('*', requireAuth())\n\n// Upload single file\napiMediaRoutes.post('/upload', async (c) => {\n try {\n const user = c.get('user')!\n const formData = await c.req.formData()\n const fileData = formData.get('file')\n\n if (!fileData || typeof fileData === 'string') {\n return c.json({ error: 'No file provided' }, 400)\n }\n\n const file = fileData as File\n\n // Validate file\n const validation = fileValidationSchema.safeParse({\n name: file.name,\n type: file.type,\n size: file.size\n })\n\n if (!validation.success) {\n return c.json({ \n error: 'File validation failed', \n details: validation.error.issues \n }, 400)\n }\n\n // Generate unique filename and R2 key\n const fileId = generateId()\n const fileExtension = file.name.split('.').pop() || ''\n const filename = `${fileId}.${fileExtension}`\n const folder = formData.get('folder') as string || 'uploads'\n const r2Key = `${folder}/${filename}`\n\n // Upload to R2\n const arrayBuffer = await file.arrayBuffer()\n const uploadResult = await c.env.MEDIA_BUCKET.put(r2Key, arrayBuffer, {\n httpMetadata: {\n contentType: file.type,\n contentDisposition: `inline; filename=\"${file.name}\"`\n },\n customMetadata: {\n originalName: file.name,\n uploadedBy: user.userId,\n uploadedAt: new Date().toISOString()\n }\n })\n\n if (!uploadResult) {\n return c.json({ error: 'Failed to upload file to storage' }, 500)\n }\n\n // Generate public URL using environment variable for bucket name\n const bucketName = c.env.BUCKET_NAME || 'sonicjs-media-dev'\n const publicUrl = `https://pub-${bucketName}.r2.dev/${r2Key}`\n \n // Extract image dimensions if it's an image\n let width: number | undefined\n let height: number | undefined\n \n if (file.type.startsWith('image/') && !file.type.includes('svg')) {\n try {\n const dimensions = await getImageDimensions(arrayBuffer)\n width = dimensions.width\n height = dimensions.height\n } catch (error) {\n console.warn('Failed to extract image dimensions:', error)\n }\n }\n\n // Generate thumbnail URL for images\n let thumbnailUrl: string | undefined\n if (file.type.startsWith('image/') && c.env.IMAGES_ACCOUNT_ID) {\n thumbnailUrl = `https://imagedelivery.net/${c.env.IMAGES_ACCOUNT_ID}/${r2Key}/thumbnail`\n }\n\n // Save to database\n const mediaRecord = {\n id: fileId,\n filename: filename,\n original_name: file.name,\n mime_type: file.type,\n size: file.size,\n width,\n height,\n folder,\n r2_key: r2Key,\n public_url: publicUrl,\n thumbnail_url: thumbnailUrl,\n uploaded_by: user.userId,\n uploaded_at: Math.floor(Date.now() / 1000),\n created_at: Math.floor(Date.now() / 1000)\n }\n\n const stmt = c.env.DB.prepare(`\n INSERT INTO media (\n id, filename, original_name, mime_type, size, width, height, \n folder, r2_key, public_url, thumbnail_url, uploaded_by, uploaded_at\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n `)\n \n await stmt.bind(\n mediaRecord.id,\n mediaRecord.filename,\n mediaRecord.original_name,\n mediaRecord.mime_type,\n mediaRecord.size,\n mediaRecord.width ?? null,\n mediaRecord.height ?? null,\n mediaRecord.folder,\n mediaRecord.r2_key,\n mediaRecord.public_url,\n mediaRecord.thumbnail_url ?? null,\n mediaRecord.uploaded_by,\n mediaRecord.uploaded_at\n ).run()\n\n // Emit media upload event\n await emitEvent('media.upload', { id: mediaRecord.id, filename: mediaRecord.filename })\n\n return c.json({\n success: true,\n file: {\n id: mediaRecord.id,\n filename: mediaRecord.filename,\n originalName: mediaRecord.original_name,\n mimeType: mediaRecord.mime_type,\n size: mediaRecord.size,\n width: mediaRecord.width,\n height: mediaRecord.height,\n r2_key: mediaRecord.r2_key,\n publicUrl: mediaRecord.public_url,\n thumbnailUrl: mediaRecord.thumbnail_url,\n uploadedAt: new Date(mediaRecord.uploaded_at * 1000).toISOString()\n }\n })\n } catch (error) {\n console.error('Upload error:', error)\n return c.json({ error: 'Upload failed' }, 500)\n }\n})\n\n// Upload multiple files\napiMediaRoutes.post('/upload-multiple', async (c) => {\n try {\n const user = c.get('user')!\n const formData = await c.req.formData()\n const filesData = formData.getAll('files')\n\n // Filter out strings and ensure we only have File objects\n const files: File[] = []\n for (const f of filesData) {\n if (typeof f !== 'string') {\n files.push(f as File)\n }\n }\n\n if (!files || files.length === 0) {\n return c.json({ error: 'No files provided' }, 400)\n }\n\n const uploadResults = []\n const errors = []\n\n for (const file of files) {\n try {\n // Validate file\n const validation = fileValidationSchema.safeParse({\n name: file.name,\n type: file.type,\n size: file.size\n })\n\n if (!validation.success) {\n errors.push({\n filename: file.name,\n error: 'Validation failed',\n details: validation.error.issues\n })\n continue\n }\n\n // Generate unique filename and R2 key\n const fileId = generateId()\n const fileExtension = file.name.split('.').pop() || ''\n const filename = `${fileId}.${fileExtension}`\n const folder = formData.get('folder') as string || 'uploads'\n const r2Key = `${folder}/${filename}`\n\n // Upload to R2\n const arrayBuffer = await file.arrayBuffer()\n const uploadResult = await c.env.MEDIA_BUCKET.put(r2Key, arrayBuffer, {\n httpMetadata: {\n contentType: file.type,\n contentDisposition: `inline; filename=\"${file.name}\"`\n },\n customMetadata: {\n originalName: file.name,\n uploadedBy: user.userId,\n uploadedAt: new Date().toISOString()\n }\n })\n\n if (!uploadResult) {\n errors.push({\n filename: file.name,\n error: 'Failed to upload to storage'\n })\n continue\n }\n\n // Generate public URL using environment variable for bucket name\n const bucketName = c.env.BUCKET_NAME || 'sonicjs-media-dev'\n const publicUrl = `https://pub-${bucketName}.r2.dev/${r2Key}`\n \n // Extract image dimensions if it's an image\n let width: number | undefined\n let height: number | undefined\n \n if (file.type.startsWith('image/') && !file.type.includes('svg')) {\n try {\n const dimensions = await getImageDimensions(arrayBuffer)\n width = dimensions.width\n height = dimensions.height\n } catch (error) {\n console.warn('Failed to extract image dimensions:', error)\n }\n }\n\n // Generate thumbnail URL for images\n let thumbnailUrl: string | undefined\n if (file.type.startsWith('image/') && c.env.IMAGES_ACCOUNT_ID) {\n thumbnailUrl = `https://imagedelivery.net/${c.env.IMAGES_ACCOUNT_ID}/${r2Key}/thumbnail`\n }\n\n // Save to database\n const mediaRecord = {\n id: fileId,\n filename: filename,\n original_name: file.name,\n mime_type: file.type,\n size: file.size,\n width,\n height,\n folder,\n r2_key: r2Key,\n public_url: publicUrl,\n thumbnail_url: thumbnailUrl,\n uploaded_by: user.userId,\n uploaded_at: Math.floor(Date.now() / 1000)\n }\n\n const stmt = c.env.DB.prepare(`\n INSERT INTO media (\n id, filename, original_name, mime_type, size, width, height, \n folder, r2_key, public_url, thumbnail_url, uploaded_by, uploaded_at\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n `)\n \n await stmt.bind(\n mediaRecord.id,\n mediaRecord.filename,\n mediaRecord.original_name,\n mediaRecord.mime_type,\n mediaRecord.size,\n mediaRecord.width ?? null,\n mediaRecord.height ?? null,\n mediaRecord.folder,\n mediaRecord.r2_key,\n mediaRecord.public_url,\n mediaRecord.thumbnail_url ?? null,\n mediaRecord.uploaded_by,\n mediaRecord.uploaded_at\n ).run()\n\n uploadResults.push({\n id: mediaRecord.id,\n filename: mediaRecord.filename,\n originalName: mediaRecord.original_name,\n mimeType: mediaRecord.mime_type,\n size: mediaRecord.size,\n width: mediaRecord.width,\n height: mediaRecord.height,\n r2_key: mediaRecord.r2_key,\n publicUrl: mediaRecord.public_url,\n thumbnailUrl: mediaRecord.thumbnail_url,\n uploadedAt: new Date(mediaRecord.uploaded_at * 1000).toISOString()\n })\n } catch (error) {\n errors.push({\n filename: file.name,\n error: 'Upload failed',\n details: error instanceof Error ? error.message : 'Unknown error'\n })\n }\n }\n\n // Emit media upload event if any uploads succeeded\n if (uploadResults.length > 0) {\n await emitEvent('media.upload', { count: uploadResults.length })\n }\n\n return c.json({\n success: uploadResults.length > 0,\n uploaded: uploadResults,\n errors: errors,\n summary: {\n total: files.length,\n successful: uploadResults.length,\n failed: errors.length\n }\n })\n } catch (error) {\n console.error('Multiple upload error:', error)\n return c.json({ error: 'Upload failed' }, 500)\n }\n})\n\n// Bulk delete files\napiMediaRoutes.post('/bulk-delete', async (c) => {\n try {\n const user = c.get('user')!\n const body = await c.req.json()\n const fileIds = body.fileIds as string[]\n \n if (!fileIds || !Array.isArray(fileIds) || fileIds.length === 0) {\n return c.json({ error: 'No file IDs provided' }, 400)\n }\n\n // Limit bulk operations to prevent abuse\n if (fileIds.length > 50) {\n return c.json({ error: 'Too many files selected. Maximum 50 files per operation.' }, 400)\n }\n\n const results = []\n const errors = []\n\n for (const fileId of fileIds) {\n try {\n // Get file record (including already deleted files to check if they exist at all)\n const stmt = c.env.DB.prepare('SELECT * FROM media WHERE id = ?')\n const fileRecord = await stmt.bind(fileId).first() as any\n\n if (!fileRecord) {\n errors.push({ fileId, error: 'File not found' })\n continue\n }\n\n // Skip if already deleted (treat as success)\n if (fileRecord.deleted_at !== null) {\n console.log(`File ${fileId} already deleted, skipping`)\n results.push({\n fileId,\n filename: fileRecord.original_name,\n success: true,\n alreadyDeleted: true\n })\n continue\n }\n\n // Check permissions (only allow deletion by uploader or admin)\n if (fileRecord.uploaded_by !== user.userId && user.role !== 'admin') {\n errors.push({ fileId, error: 'Permission denied' })\n continue\n }\n\n // Delete from R2\n try {\n await c.env.MEDIA_BUCKET.delete(fileRecord.r2_key)\n } catch (error) {\n console.warn(`Failed to delete from R2 for file ${fileId}:`, error)\n // Continue with database deletion even if R2 deletion fails\n }\n\n // Soft delete in database\n const deleteStmt = c.env.DB.prepare('UPDATE media SET deleted_at = ? WHERE id = ?')\n await deleteStmt.bind(Math.floor(Date.now() / 1000), fileId).run()\n\n results.push({\n fileId,\n filename: fileRecord.original_name,\n success: true\n })\n } catch (error) {\n errors.push({\n fileId,\n error: 'Delete failed',\n details: error instanceof Error ? error.message : 'Unknown error'\n })\n }\n }\n\n // Emit media delete event if any deletes succeeded\n if (results.length > 0) {\n await emitEvent('media.delete', { count: results.length, ids: fileIds })\n }\n\n return c.json({\n success: results.length > 0,\n deleted: results,\n errors: errors,\n summary: {\n total: fileIds.length,\n successful: results.length,\n failed: errors.length\n }\n })\n } catch (error) {\n console.error('Bulk delete error:', error)\n return c.json({ error: 'Bulk delete failed' }, 500)\n }\n})\n\n// Create folder\napiMediaRoutes.post('/create-folder', async (c) => {\n try {\n const body = await c.req.json()\n const folderName = body.folderName as string\n\n if (!folderName || typeof folderName !== 'string') {\n return c.json({ success: false, error: 'No folder name provided' }, 400)\n }\n\n // Validate folder name format\n const folderPattern = /^[a-z0-9-_]+$/\n if (!folderPattern.test(folderName)) {\n return c.json({\n success: false,\n error: 'Folder name can only contain lowercase letters, numbers, hyphens, and underscores'\n }, 400)\n }\n\n // Check if folder already exists in the database\n const checkStmt = c.env.DB.prepare('SELECT COUNT(*) as count FROM media WHERE folder = ? AND deleted_at IS NULL')\n const existingFolder = await checkStmt.bind(folderName).first() as any\n\n if (existingFolder && existingFolder.count > 0) {\n return c.json({\n success: false,\n error: `Folder \"${folderName}\" already exists`\n }, 400)\n }\n\n // Note: R2 folders are virtual - they only exist when files are uploaded to them\n // Return success message explaining this behavior\n return c.json({\n success: true,\n message: `Folder \"${folderName}\" is ready. Upload files to this folder to make it appear in the media library.`,\n folder: folderName,\n note: 'Folders appear automatically when you upload files to them'\n })\n } catch (error) {\n console.error('Create folder error:', error)\n return c.json({ success: false, error: 'Failed to create folder' }, 500)\n }\n})\n\n// Bulk move files to folder\napiMediaRoutes.post('/bulk-move', async (c) => {\n try {\n const user = c.get('user')!\n const body = await c.req.json()\n const fileIds = body.fileIds as string[]\n const targetFolder = body.folder as string\n\n if (!fileIds || !Array.isArray(fileIds) || fileIds.length === 0) {\n return c.json({ error: 'No file IDs provided' }, 400)\n }\n\n if (!targetFolder || typeof targetFolder !== 'string') {\n return c.json({ error: 'No target folder provided' }, 400)\n }\n\n // Limit bulk operations to prevent abuse\n if (fileIds.length > 50) {\n return c.json({ error: 'Too many files selected. Maximum 50 files per operation.' }, 400)\n }\n\n const results = []\n const errors = []\n\n for (const fileId of fileIds) {\n try {\n // Get file record\n const stmt = c.env.DB.prepare('SELECT * FROM media WHERE id = ? AND deleted_at IS NULL')\n const fileRecord = await stmt.bind(fileId).first() as any\n\n if (!fileRecord) {\n errors.push({ fileId, error: 'File not found' })\n continue\n }\n\n // Check permissions (only allow move by uploader or admin)\n if (fileRecord.uploaded_by !== user.userId && user.role !== 'admin') {\n errors.push({ fileId, error: 'Permission denied' })\n continue\n }\n\n // Skip if already in target folder\n if (fileRecord.folder === targetFolder) {\n results.push({\n fileId,\n filename: fileRecord.original_name,\n success: true,\n skipped: true\n })\n continue\n }\n\n // Generate new R2 key with new folder\n const oldR2Key = fileRecord.r2_key\n const filename = oldR2Key.split('/').pop() || fileRecord.filename\n const newR2Key = `${targetFolder}/${filename}`\n\n // Copy file to new location in R2\n try {\n const object = await c.env.MEDIA_BUCKET.get(oldR2Key)\n if (!object) {\n errors.push({ fileId, error: 'File not found in storage' })\n continue\n }\n\n await c.env.MEDIA_BUCKET.put(newR2Key, object.body, {\n httpMetadata: object.httpMetadata,\n customMetadata: {\n ...object.customMetadata,\n movedBy: user.userId,\n movedAt: new Date().toISOString()\n }\n })\n\n // Delete old file from R2\n await c.env.MEDIA_BUCKET.delete(oldR2Key)\n } catch (error) {\n console.warn(`Failed to move file in R2 for file ${fileId}:`, error)\n errors.push({ fileId, error: 'Failed to move file in storage' })\n continue\n }\n\n // Update database with new folder and R2 key\n const bucketName = c.env.BUCKET_NAME || 'sonicjs-media-dev'\n const newPublicUrl = `https://pub-${bucketName}.r2.dev/${newR2Key}`\n\n const updateStmt = c.env.DB.prepare(`\n UPDATE media\n SET folder = ?, r2_key = ?, public_url = ?, updated_at = ?\n WHERE id = ?\n `)\n await updateStmt.bind(\n targetFolder,\n newR2Key,\n newPublicUrl,\n Math.floor(Date.now() / 1000),\n fileId\n ).run()\n\n results.push({\n fileId,\n filename: fileRecord.original_name,\n success: true,\n skipped: false\n })\n } catch (error) {\n errors.push({\n fileId,\n error: 'Move failed',\n details: error instanceof Error ? error.message : 'Unknown error'\n })\n }\n }\n\n // Emit media move event if any moves succeeded\n if (results.length > 0) {\n await emitEvent('media.move', { count: results.length, targetFolder, ids: fileIds })\n }\n\n return c.json({\n success: results.length > 0,\n moved: results,\n errors: errors,\n summary: {\n total: fileIds.length,\n successful: results.length,\n failed: errors.length\n }\n })\n } catch (error) {\n console.error('Bulk move error:', error)\n return c.json({ error: 'Bulk move failed' }, 500)\n }\n})\n\n// Delete file\napiMediaRoutes.delete('/:id', async (c) => {\n try {\n const user = c.get('user')!\n const fileId = c.req.param('id')\n \n // Get file record\n const stmt = c.env.DB.prepare('SELECT * FROM media WHERE id = ? AND deleted_at IS NULL')\n const fileRecord = await stmt.bind(fileId).first() as any\n \n if (!fileRecord) {\n return c.json({ error: 'File not found' }, 404)\n }\n\n // Check permissions (only allow deletion by uploader or admin)\n if (fileRecord.uploaded_by !== user.userId && user.role !== 'admin') {\n return c.json({ error: 'Permission denied' }, 403)\n }\n\n // Delete from R2\n try {\n await c.env.MEDIA_BUCKET.delete(fileRecord.r2_key)\n } catch (error) {\n console.warn('Failed to delete from R2:', error)\n // Continue with database deletion even if R2 deletion fails\n }\n\n // Soft delete in database\n const deleteStmt = c.env.DB.prepare('UPDATE media SET deleted_at = ? WHERE id = ?')\n await deleteStmt.bind(Math.floor(Date.now() / 1000), fileId).run()\n\n // Emit media delete event\n await emitEvent('media.delete', { id: fileId })\n\n return c.json({ success: true, message: 'File deleted successfully' })\n } catch (error) {\n console.error('Delete error:', error)\n return c.json({ error: 'Delete failed' }, 500)\n }\n})\n\n// Update file metadata\napiMediaRoutes.patch('/:id', async (c) => {\n try {\n const user = c.get('user')!\n const fileId = c.req.param('id')\n const body = await c.req.json()\n \n // Get file record\n const stmt = c.env.DB.prepare('SELECT * FROM media WHERE id = ? AND deleted_at IS NULL')\n const fileRecord = await stmt.bind(fileId).first() as any\n \n if (!fileRecord) {\n return c.json({ error: 'File not found' }, 404)\n }\n\n // Check permissions (only allow updates by uploader or admin)\n if (fileRecord.uploaded_by !== user.userId && user.role !== 'admin') {\n return c.json({ error: 'Permission denied' }, 403)\n }\n\n // Update allowed fields\n const allowedFields = ['alt', 'caption', 'tags', 'folder']\n const updates = []\n const values = []\n \n for (const [key, value] of Object.entries(body)) {\n if (allowedFields.includes(key)) {\n updates.push(`${key} = ?`)\n values.push(key === 'tags' ? JSON.stringify(value) : value)\n }\n }\n\n if (updates.length === 0) {\n return c.json({ error: 'No valid fields to update' }, 400)\n }\n\n updates.push('updated_at = ?')\n values.push(Math.floor(Date.now() / 1000))\n values.push(fileId)\n\n const updateStmt = c.env.DB.prepare(`\n UPDATE media SET ${updates.join(', ')} WHERE id = ?\n `)\n await updateStmt.bind(...values).run()\n\n // Emit media update event\n await emitEvent('media.update', { id: fileId })\n\n return c.json({ success: true, message: 'File updated successfully' })\n } catch (error) {\n console.error('Update error:', error)\n return c.json({ error: 'Update failed' }, 500)\n }\n})\n\n// Helper function to extract image dimensions\nasync function getImageDimensions(arrayBuffer: ArrayBuffer): Promise<{ width: number; height: number }> {\n // This is a simplified implementation\n // In a real-world scenario, you'd use a proper image processing library\n const uint8Array = new Uint8Array(arrayBuffer)\n \n // Check for JPEG\n if (uint8Array[0] === 0xFF && uint8Array[1] === 0xD8) {\n return getJPEGDimensions(uint8Array)\n }\n \n // Check for PNG\n if (uint8Array[0] === 0x89 && uint8Array[1] === 0x50 && uint8Array[2] === 0x4E && uint8Array[3] === 0x47) {\n return getPNGDimensions(uint8Array)\n }\n \n // Default fallback\n return { width: 0, height: 0 }\n}\n\nfunction getJPEGDimensions(uint8Array: Uint8Array): { width: number; height: number } {\n let i = 2\n while (i < uint8Array.length) {\n if (i + 8 >= uint8Array.length) break\n if (uint8Array[i] === 0xFF && uint8Array[i + 1] === 0xC0) {\n if (i + 8 < uint8Array.length) {\n return {\n height: (uint8Array[i + 5]! << 8) | uint8Array[i + 6]!,\n width: (uint8Array[i + 7]! << 8) | uint8Array[i + 8]!\n }\n }\n }\n if (i + 3 < uint8Array.length) {\n i += 2 + ((uint8Array[i + 2]! << 8) | uint8Array[i + 3]!)\n } else {\n break\n }\n }\n return { width: 0, height: 0 }\n}\n\nfunction getPNGDimensions(uint8Array: Uint8Array): { width: number; height: number } {\n if (uint8Array.length < 24) {\n return { width: 0, height: 0 }\n }\n return {\n width: (uint8Array[16]! << 24) | (uint8Array[17]! << 16) | (uint8Array[18]! << 8) | uint8Array[19]!,\n height: (uint8Array[20]! << 24) | (uint8Array[21]! << 16) | (uint8Array[22]! << 8) | uint8Array[23]!\n }\n}\n\nexport default apiMediaRoutes","/**\n * API System Routes\n *\n * Provides system health, status, and metadata endpoints\n * These are lightweight routes without heavy dependencies\n */\n\nimport { Hono } from 'hono'\nimport type { Bindings, Variables } from '../app'\n\nexport const apiSystemRoutes = new Hono<{ Bindings: Bindings; Variables: Variables }>()\n\n/**\n * System health check\n * GET /api/system/health\n */\napiSystemRoutes.get('/health', async (c) => {\n try {\n const startTime = Date.now()\n\n // Check database connectivity\n let dbStatus = 'unknown'\n let dbLatency = 0\n\n try {\n const dbStart = Date.now()\n await c.env.DB.prepare('SELECT 1').first()\n dbLatency = Date.now() - dbStart\n dbStatus = 'healthy'\n } catch (error) {\n console.error('Database health check failed:', error)\n dbStatus = 'unhealthy'\n }\n\n // Check KV connectivity (if available)\n let kvStatus = 'not_configured'\n let kvLatency = 0\n\n if (c.env.CACHE_KV) {\n try {\n const kvStart = Date.now()\n await c.env.CACHE_KV.get('__health_check__')\n kvLatency = Date.now() - kvStart\n kvStatus = 'healthy'\n } catch (error) {\n console.error('KV health check failed:', error)\n kvStatus = 'unhealthy'\n }\n }\n\n // Check R2 connectivity (if available)\n let r2Status = 'not_configured'\n\n if (c.env.MEDIA_BUCKET) {\n try {\n await c.env.MEDIA_BUCKET.head('__health_check__')\n r2Status = 'healthy'\n } catch (error) {\n // R2 head on non-existent key returns null, not an error\n // This is expected, so we consider it healthy\n r2Status = 'healthy'\n }\n }\n\n const totalLatency = Date.now() - startTime\n const overall = dbStatus === 'healthy' ? 'healthy' : 'degraded'\n\n return c.json({\n status: overall,\n timestamp: new Date().toISOString(),\n uptime: totalLatency,\n checks: {\n database: {\n status: dbStatus,\n latency: dbLatency\n },\n cache: {\n status: kvStatus,\n latency: kvLatency\n },\n storage: {\n status: r2Status\n }\n },\n environment: c.env.ENVIRONMENT || 'production'\n })\n } catch (error) {\n console.error('Health check failed:', error)\n return c.json({\n status: 'unhealthy',\n timestamp: new Date().toISOString(),\n error: 'Health check failed'\n }, 503)\n }\n})\n\n/**\n * System information\n * GET /api/system/info\n */\napiSystemRoutes.get('/info', (c) => {\n const appVersion = c.get('appVersion') || '1.0.0'\n\n return c.json({\n name: 'SonicJS',\n version: appVersion,\n description: 'Modern headless CMS built on Cloudflare Workers',\n endpoints: {\n api: '/api',\n auth: '/auth',\n health: '/api/system/health',\n docs: '/docs'\n },\n features: {\n content: true,\n media: true,\n auth: true,\n collections: true,\n caching: !!c.env.CACHE_KV,\n storage: !!c.env.MEDIA_BUCKET\n },\n timestamp: new Date().toISOString()\n })\n})\n\n/**\n * System stats\n * GET /api/system/stats\n */\napiSystemRoutes.get('/stats', async (c) => {\n try {\n const db = c.env.DB\n\n // Get content statistics\n const contentStats = await db.prepare(`\n SELECT COUNT(*) as total_content\n FROM content\n WHERE deleted_at IS NULL\n `).first() as any\n\n // Get media statistics\n const mediaStats = await db.prepare(`\n SELECT\n COUNT(*) as total_files,\n SUM(size) as total_size\n FROM media\n WHERE deleted_at IS NULL\n `).first() as any\n\n // Get user statistics\n const userStats = await db.prepare(`\n SELECT COUNT(*) as total_users\n FROM users\n `).first() as any\n\n return c.json({\n content: {\n total: contentStats?.total_content || 0\n },\n media: {\n total_files: mediaStats?.total_files || 0,\n total_size_bytes: mediaStats?.total_size || 0,\n total_size_mb: Math.round((mediaStats?.total_size || 0) / 1024 / 1024 * 100) / 100\n },\n users: {\n total: userStats?.total_users || 0\n },\n timestamp: new Date().toISOString()\n })\n } catch (error) {\n console.error('Stats query failed:', error)\n return c.json({ error: 'Failed to fetch system statistics' }, 500)\n }\n})\n\n/**\n * Database ping\n * GET /api/system/ping\n */\napiSystemRoutes.get('/ping', async (c) => {\n try {\n const start = Date.now()\n await c.env.DB.prepare('SELECT 1').first()\n const latency = Date.now() - start\n\n return c.json({\n pong: true,\n latency,\n timestamp: new Date().toISOString()\n })\n } catch (error) {\n console.error('Ping failed:', error)\n return c.json({\n pong: false,\n error: 'Database connection failed'\n }, 503)\n }\n})\n\n/**\n * Environment check\n * GET /api/system/env\n */\napiSystemRoutes.get('/env', (c) => {\n return c.json({\n environment: c.env.ENVIRONMENT || 'production',\n features: {\n database: !!c.env.DB,\n cache: !!c.env.CACHE_KV,\n media_bucket: !!c.env.MEDIA_BUCKET,\n email_queue: !!c.env.EMAIL_QUEUE,\n sendgrid: !!c.env.SENDGRID_API_KEY,\n cloudflare_images: !!(c.env.IMAGES_ACCOUNT_ID && c.env.IMAGES_API_TOKEN)\n },\n timestamp: new Date().toISOString()\n })\n})\n\nexport default apiSystemRoutes\n","/**\n * Admin API Routes\n *\n * Provides JSON API endpoints for admin operations\n * These routes complement the admin UI and can be used programmatically\n */\n\nimport { Hono } from 'hono'\nimport { z } from 'zod'\n// import { zValidator } from '@hono/zod-validator'\nimport { requireAuth, requireRole } from '../middleware'\nimport type { Bindings, Variables } from '../app'\n\nexport const adminApiRoutes = new Hono<{ Bindings: Bindings; Variables: Variables }>()\n\n// Apply auth middleware to all admin routes\nadminApiRoutes.use('*', requireAuth())\nadminApiRoutes.use('*', requireRole(['admin', 'editor']))\n\n/**\n * Get dashboard statistics\n * GET /admin/api/stats\n */\nadminApiRoutes.get('/stats', async (c) => {\n try {\n const db = c.env.DB\n\n // Get collections count\n let collectionsCount = 0\n try {\n const collectionsStmt = db.prepare('SELECT COUNT(*) as count FROM collections WHERE is_active = 1')\n const collectionsResult = await collectionsStmt.first()\n collectionsCount = (collectionsResult as any)?.count || 0\n } catch (error) {\n console.error('Error fetching collections count:', error)\n }\n\n // Get content count\n let contentCount = 0\n try {\n const contentStmt = db.prepare('SELECT COUNT(*) as count FROM content WHERE deleted_at IS NULL')\n const contentResult = await contentStmt.first()\n contentCount = (contentResult as any)?.count || 0\n } catch (error) {\n console.error('Error fetching content count:', error)\n }\n\n // Get media count and total size\n let mediaCount = 0\n let mediaSize = 0\n try {\n const mediaStmt = db.prepare('SELECT COUNT(*) as count, COALESCE(SUM(size), 0) as total_size FROM media WHERE deleted_at IS NULL')\n const mediaResult = await mediaStmt.first()\n mediaCount = (mediaResult as any)?.count || 0\n mediaSize = (mediaResult as any)?.total_size || 0\n } catch (error) {\n console.error('Error fetching media count:', error)\n }\n\n // Get users count\n let usersCount = 0\n try {\n const usersStmt = db.prepare('SELECT COUNT(*) as count FROM users WHERE is_active = 1')\n const usersResult = await usersStmt.first()\n usersCount = (usersResult as any)?.count || 0\n } catch (error) {\n console.error('Error fetching users count:', error)\n }\n\n return c.json({\n collections: collectionsCount,\n contentItems: contentCount,\n mediaFiles: mediaCount,\n mediaSize: mediaSize,\n users: usersCount,\n timestamp: new Date().toISOString()\n })\n } catch (error) {\n console.error('Error fetching stats:', error)\n return c.json({ error: 'Failed to fetch statistics' }, 500)\n }\n})\n\n/**\n * Get storage usage\n * GET /admin/api/storage\n */\nadminApiRoutes.get('/storage', async (c) => {\n try {\n const db = c.env.DB\n\n // Get database size from D1 metadata\n let databaseSize = 0\n try {\n const result = await db.prepare('SELECT 1').run()\n databaseSize = (result as any)?.meta?.size_after || 0\n } catch (error) {\n console.error('Error fetching database size:', error)\n }\n\n // Get media total size\n let mediaSize = 0\n try {\n const mediaStmt = db.prepare('SELECT COALESCE(SUM(size), 0) as total_size FROM media WHERE deleted_at IS NULL')\n const mediaResult = await mediaStmt.first()\n mediaSize = (mediaResult as any)?.total_size || 0\n } catch (error) {\n console.error('Error fetching media size:', error)\n }\n\n return c.json({\n databaseSize,\n mediaSize,\n totalSize: databaseSize + mediaSize,\n timestamp: new Date().toISOString()\n })\n } catch (error) {\n console.error('Error fetching storage usage:', error)\n return c.json({ error: 'Failed to fetch storage usage' }, 500)\n }\n})\n\n/**\n * Get recent activity\n * GET /admin/api/activity\n */\nadminApiRoutes.get('/activity', async (c) => {\n try {\n const db = c.env.DB\n const limit = parseInt(c.req.query('limit') || '10')\n\n // Get recent activities from activity_logs table\n const activityStmt = db.prepare(`\n SELECT\n a.id,\n a.action,\n a.resource_type,\n a.resource_id,\n a.details,\n a.created_at,\n u.email,\n u.first_name,\n u.last_name\n FROM activity_logs a\n LEFT JOIN users u ON a.user_id = u.id\n WHERE a.resource_type IN ('content', 'collections', 'users', 'media')\n ORDER BY a.created_at DESC\n LIMIT ?\n `)\n\n const { results } = await activityStmt.bind(limit).all()\n\n const recentActivity = (results || []).map((row: any) => {\n const userName = row.first_name && row.last_name\n ? `${row.first_name} ${row.last_name}`\n : row.email || 'System'\n\n let details: any = {}\n try {\n details = row.details ? JSON.parse(row.details) : {}\n } catch (e) {\n console.error('Error parsing activity details:', e)\n }\n\n return {\n id: row.id,\n type: row.resource_type,\n action: row.action,\n resource_id: row.resource_id,\n details,\n timestamp: new Date(Number(row.created_at)).toISOString(),\n user: userName\n }\n })\n\n return c.json({\n data: recentActivity,\n count: recentActivity.length,\n timestamp: new Date().toISOString()\n })\n } catch (error) {\n console.error('Error fetching recent activity:', error)\n return c.json({ error: 'Failed to fetch recent activity' }, 500)\n }\n})\n\n/**\n * Collection management schema\n */\nconst createCollectionSchema = z.object({\n name: z.string().min(1).max(255).regex(/^[a-z0-9_]+$/, 'Must contain only lowercase letters, numbers, and underscores'),\n displayName: z.string().min(1).max(255).optional(),\n display_name: z.string().min(1).max(255).optional(),\n description: z.string().optional()\n}).refine(data => data.displayName || data.display_name, {\n message: 'Either displayName or display_name is required',\n path: ['displayName']\n})\n\nconst updateCollectionSchema = z.object({\n display_name: z.string().min(1).max(255).optional(),\n description: z.string().optional(),\n is_active: z.boolean().optional()\n})\n\n/**\n * Get all collections\n * GET /admin/api/collections\n */\nadminApiRoutes.get('/collections', async (c) => {\n try {\n const db = c.env.DB\n const search = c.req.query('search') || ''\n const includeInactive = c.req.query('includeInactive') === 'true'\n\n let stmt\n let results\n\n if (search) {\n stmt = db.prepare(`\n SELECT id, name, display_name, description, created_at, updated_at, is_active, managed\n FROM collections\n WHERE ${includeInactive ? '1=1' : 'is_active = 1'}\n AND (name LIKE ? OR display_name LIKE ? OR description LIKE ?)\n ORDER BY created_at DESC\n `)\n const searchParam = `%${search}%`\n const queryResults = await stmt.bind(searchParam, searchParam, searchParam).all()\n results = queryResults.results\n } else {\n stmt = db.prepare(`\n SELECT id, name, display_name, description, created_at, updated_at, is_active, managed\n FROM collections\n ${includeInactive ? '' : 'WHERE is_active = 1'}\n ORDER BY created_at DESC\n `)\n const queryResults = await stmt.all()\n results = queryResults.results\n }\n\n // Get field counts\n const fieldCountStmt = db.prepare('SELECT collection_id, COUNT(*) as count FROM content_fields GROUP BY collection_id')\n const { results: fieldCountResults } = await fieldCountStmt.all()\n const fieldCounts = new Map((fieldCountResults || []).map((row: any) => [String(row.collection_id), Number(row.count)]))\n\n const collections = (results || []).map((row: any) => ({\n id: row.id,\n name: row.name,\n display_name: row.display_name,\n description: row.description,\n created_at: Number(row.created_at),\n updated_at: Number(row.updated_at),\n is_active: row.is_active === 1,\n managed: row.managed === 1,\n field_count: fieldCounts.get(String(row.id)) || 0\n }))\n\n return c.json({\n data: collections,\n count: collections.length,\n timestamp: new Date().toISOString()\n })\n } catch (error) {\n console.error('Error fetching collections:', error)\n return c.json({ error: 'Failed to fetch collections' }, 500)\n }\n})\n\n/**\n * Get single collection\n * GET /admin/api/collections/:id\n */\nadminApiRoutes.get('/collections/:id', async (c) => {\n try {\n const id = c.req.param('id')\n const db = c.env.DB\n\n const stmt = db.prepare('SELECT * FROM collections WHERE id = ?')\n const collection = await stmt.bind(id).first() as any\n\n if (!collection) {\n return c.json({ error: 'Collection not found' }, 404)\n }\n\n // Get collection fields\n const fieldsStmt = db.prepare(`\n SELECT * FROM content_fields\n WHERE collection_id = ?\n ORDER BY field_order ASC\n `)\n const { results: fieldsResults } = await fieldsStmt.bind(id).all()\n\n const fields = (fieldsResults || []).map((row: any) => ({\n id: row.id,\n field_name: row.field_name,\n field_type: row.field_type,\n field_label: row.field_label,\n field_options: row.field_options ? JSON.parse(row.field_options) : {},\n field_order: row.field_order,\n is_required: row.is_required === 1,\n is_searchable: row.is_searchable === 1,\n created_at: Number(row.created_at),\n updated_at: Number(row.updated_at)\n }))\n\n return c.json({\n id: collection.id,\n name: collection.name,\n display_name: collection.display_name,\n description: collection.description,\n is_active: collection.is_active === 1,\n managed: collection.managed === 1,\n schema: collection.schema ? JSON.parse(collection.schema) : null,\n created_at: Number(collection.created_at),\n updated_at: Number(collection.updated_at),\n fields\n })\n } catch (error) {\n console.error('Error fetching collection:', error)\n return c.json({ error: 'Failed to fetch collection' }, 500)\n }\n})\n\n/**\n * Create collection\n * POST /admin/api/collections\n */\nadminApiRoutes.post('/collections', async (c) => {\n try {\n // Validate content type\n const contentType = c.req.header('Content-Type')\n if (!contentType || !contentType.includes('application/json')) {\n return c.json({ error: 'Content-Type must be application/json' }, 400)\n }\n\n let body\n try {\n body = await c.req.json()\n } catch (e) {\n return c.json({ error: 'Invalid JSON in request body' }, 400)\n }\n\n const validation = createCollectionSchema.safeParse(body)\n if (!validation.success) {\n return c.json({ error: 'Validation failed', details: validation.error.issues }, 400)\n }\n const validatedData = validation.data\n const db = c.env.DB\n const ____user = c.get('user')\n\n // Handle both camelCase and snake_case for display_name\n const displayName = validatedData.displayName || validatedData.display_name || ''\n\n // Check if collection already exists\n const existingStmt = db.prepare('SELECT id FROM collections WHERE name = ?')\n const existing = await existingStmt.bind(validatedData.name).first()\n\n if (existing) {\n return c.json({ error: 'A collection with this name already exists' }, 400)\n }\n\n // Create basic schema\n const basicSchema = {\n type: \"object\",\n properties: {\n title: {\n type: \"string\",\n title: \"Title\",\n required: true\n },\n content: {\n type: \"string\",\n title: \"Content\",\n format: \"richtext\"\n },\n status: {\n type: \"string\",\n title: \"Status\",\n enum: [\"draft\", \"published\", \"archived\"],\n default: \"draft\"\n }\n },\n required: [\"title\"]\n }\n\n const collectionId = crypto.randomUUID()\n const now = Date.now()\n\n const insertStmt = db.prepare(`\n INSERT INTO collections (id, name, display_name, description, schema, is_active, created_at, updated_at)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?)\n `)\n\n await insertStmt.bind(\n collectionId,\n validatedData.name,\n displayName,\n validatedData.description || null,\n JSON.stringify(basicSchema),\n 1, // is_active\n now,\n now\n ).run()\n\n // Clear cache\n try {\n await c.env.CACHE_KV.delete('cache:collections:all')\n await c.env.CACHE_KV.delete(`cache:collection:${validatedData.name}`)\n } catch (e) {\n console.error('Error clearing cache:', e)\n }\n\n return c.json({\n id: collectionId,\n name: validatedData.name,\n displayName: displayName,\n description: validatedData.description,\n created_at: now\n }, 201)\n } catch (error) {\n console.error('Error creating collection:', error)\n return c.json({ error: 'Failed to create collection' }, 500)\n }\n})\n\n/**\n * Update collection\n * PATCH /admin/api/collections/:id\n */\nadminApiRoutes.patch('/collections/:id', async (c) => {\n try {\n const id = c.req.param('id')\n const body = await c.req.json()\n const validation = updateCollectionSchema.safeParse(body)\n if (!validation.success) {\n return c.json({ error: 'Validation failed', details: validation.error.issues }, 400)\n }\n const validatedData = validation.data\n const db = c.env.DB\n\n // Check if collection exists\n const checkStmt = db.prepare('SELECT * FROM collections WHERE id = ?')\n const existing = await checkStmt.bind(id).first() as any\n\n if (!existing) {\n return c.json({ error: 'Collection not found' }, 404)\n }\n\n // Build update query\n const updateFields: string[] = []\n const updateParams: any[] = []\n\n if (validatedData.display_name !== undefined) {\n updateFields.push('display_name = ?')\n updateParams.push(validatedData.display_name)\n }\n\n if (validatedData.description !== undefined) {\n updateFields.push('description = ?')\n updateParams.push(validatedData.description)\n }\n\n if (validatedData.is_active !== undefined) {\n updateFields.push('is_active = ?')\n updateParams.push(validatedData.is_active ? 1 : 0)\n }\n\n if (updateFields.length === 0) {\n return c.json({ error: 'No fields to update' }, 400)\n }\n\n updateFields.push('updated_at = ?')\n updateParams.push(Date.now())\n updateParams.push(id)\n\n const updateStmt = db.prepare(`\n UPDATE collections\n SET ${updateFields.join(', ')}\n WHERE id = ?\n `)\n\n await updateStmt.bind(...updateParams).run()\n\n // Clear cache\n try {\n await c.env.CACHE_KV.delete('cache:collections:all')\n await c.env.CACHE_KV.delete(`cache:collection:${existing.name}`)\n } catch (e) {\n console.error('Error clearing cache:', e)\n }\n\n return c.json({ message: 'Collection updated successfully' })\n } catch (error) {\n console.error('Error updating collection:', error)\n return c.json({ error: 'Failed to update collection' }, 500)\n }\n})\n\n/**\n * Delete collection\n * DELETE /admin/api/collections/:id\n */\nadminApiRoutes.delete('/collections/:id', async (c) => {\n try {\n const id = c.req.param('id')\n const db = c.env.DB\n\n // Check if collection exists\n const collectionStmt = db.prepare('SELECT name FROM collections WHERE id = ?')\n const collection = await collectionStmt.bind(id).first() as any\n\n if (!collection) {\n return c.json({ error: 'Collection not found' }, 404)\n }\n\n // Check if collection has content\n const contentStmt = db.prepare('SELECT COUNT(*) as count FROM content WHERE collection_id = ?')\n const contentResult = await contentStmt.bind(id).first() as any\n\n if (contentResult && contentResult.count > 0) {\n return c.json({\n error: `Cannot delete collection: it contains ${contentResult.count} content item(s). Delete all content first.`\n }, 400)\n }\n\n // Delete collection fields first\n const deleteFieldsStmt = db.prepare('DELETE FROM content_fields WHERE collection_id = ?')\n await deleteFieldsStmt.bind(id).run()\n\n // Delete collection\n const deleteStmt = db.prepare('DELETE FROM collections WHERE id = ?')\n await deleteStmt.bind(id).run()\n\n // Clear cache\n try {\n await c.env.CACHE_KV.delete('cache:collections:all')\n await c.env.CACHE_KV.delete(`cache:collection:${collection.name}`)\n } catch (e) {\n console.error('Error clearing cache:', e)\n }\n\n return c.json({ message: 'Collection deleted successfully' })\n } catch (error) {\n console.error('Error deleting collection:', error)\n return c.json({ error: 'Failed to delete collection' }, 500)\n }\n})\n\n// Migrations API endpoints\n// Get migration status\nadminApiRoutes.get('/migrations/status', async (c) => {\n try {\n const { MigrationService } = await import('../services/migrations')\n const db = c.env.DB\n const migrationService = new MigrationService(db)\n const status = await migrationService.getMigrationStatus()\n\n return c.json({\n success: true,\n data: status\n })\n } catch (error) {\n console.error('Error fetching migration status:', error)\n return c.json({\n success: false,\n error: 'Failed to fetch migration status'\n }, 500)\n }\n})\n\n// Run pending migrations\nadminApiRoutes.post('/migrations/run', async (c) => {\n try {\n const user = c.get('user')\n\n // Only allow admin users to run migrations\n if (!user || user.role !== 'admin') {\n return c.json({\n success: false,\n error: 'Unauthorized. Admin access required.'\n }, 403)\n }\n\n const { MigrationService } = await import('../services/migrations')\n const db = c.env.DB\n const migrationService = new MigrationService(db)\n const result = await migrationService.runPendingMigrations()\n\n return c.json({\n success: result.success,\n message: result.message,\n applied: result.applied\n })\n } catch (error) {\n console.error('Error running migrations:', error)\n return c.json({\n success: false,\n error: 'Failed to run migrations'\n }, 500)\n }\n})\n\n// Validate database schema\nadminApiRoutes.get('/migrations/validate', async (c) => {\n try {\n const { MigrationService } = await import('../services/migrations')\n const db = c.env.DB\n const migrationService = new MigrationService(db)\n const validation = await migrationService.validateSchema()\n\n return c.json({\n success: true,\n data: validation\n })\n } catch (error) {\n console.error('Error validating schema:', error)\n return c.json({\n success: false,\n error: 'Failed to validate schema'\n }, 500)\n }\n})\n\nexport default adminApiRoutes\n","import { renderAlert } from '../alert.template'\n\nexport interface LoginPageData {\n error?: string\n message?: string\n version?: string\n}\n\nexport function renderLoginPage(data: LoginPageData, demoLoginActive: boolean = false): string {\n return `\n <!DOCTYPE html>\n <html lang=\"en\" class=\"h-full dark\">\n <head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <title>Login - SonicJS AI</title>\n <link rel=\"icon\" type=\"image/x-icon\" href=\"https://demo.sonicjs.com/images/favicon.ico\">\n <script src=\"https://unpkg.com/htmx.org@2.0.3\"></script>\n <script src=\"https://cdn.tailwindcss.com\"></script>\n <script>\n tailwind.config = {\n darkMode: 'class',\n theme: {\n extend: {\n colors: {\n error: '#ef4444'\n }\n }\n }\n }\n </script>\n <style>\n @import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap');\n\n body {\n font-family: 'Inter', system-ui, -apple-system, sans-serif;\n }\n </style>\n </head>\n <body class=\"h-full bg-zinc-950\">\n <div class=\"flex min-h-full flex-col justify-center py-12 sm:px-6 lg:px-8\">\n <!-- Logo Section -->\n <div class=\"sm:mx-auto sm:w-full sm:max-w-md text-center\">\n <div class=\"mx-auto w-64 mb-8\">\n <svg class=\"w-full h-auto\" viewBox=\"380 1300 2250 400\" aria-hidden=\"true\">\n <path fill=\"#F1F2F2\" d=\"M476.851,1404.673h168.536c4.714,0,8.695-1.618,11.944-4.866c3.241-3.241,4.866-7.222,4.866-11.943 c0-2.357-0.443-4.569-1.327-6.636c-0.885-2.06-2.067-3.829-3.539-5.308c-1.479-1.472-3.249-2.654-5.308-3.538 c-2.067-0.885-4.279-1.327-6.635-1.327H476.851c-20.057,0-37.158,7.154-51.313,21.454c-14.155,14.308-21.233,31.483-21.233,51.534 c0,20.058,7.078,37.234,21.233,51.534c14.155,14.308,31.255,21.454,51.313,21.454h112.357c10.907,0,20.196,3.837,27.868,11.502 c7.666,7.672,11.502,16.885,11.502,27.646c0,10.769-3.836,19.982-11.502,27.647c-7.672,7.673-16.961,11.502-27.868,11.502H421.115 c-4.721,0-8.702,1.624-11.944,4.865c-3.248,3.249-4.866,7.23-4.866,11.944c0,3.248,0.733,6.123,2.212,8.626 c1.472,2.509,3.462,4.499,5.971,5.972c2.502,1.472,5.378,2.212,8.626,2.212h168.094c20.052,0,37.227-7.078,51.534-21.234 c14.3-14.155,21.454-31.331,21.454-51.534c0-20.196-7.154-37.379-21.454-51.534c-14.308-14.156-31.483-21.234-51.534-21.234 H476.851c-10.616,0-19.76-3.905-27.426-11.721c-7.672-7.811-11.501-17.101-11.501-27.87c0-10.761,3.829-19.975,11.501-27.647 C457.091,1408.508,466.235,1404.673,476.851,1404.673z\"></path>\n <path fill=\"#F1F2F2\" d=\"M974.78,1398.211c-5.016,6.574-10.034,13.146-15.048,19.721c-1.828,2.398-3.657,4.796-5.487,7.194 c1.994,1.719,3.958,3.51,5.873,5.424c18.724,18.731,28.089,41.216,28.089,67.459c0,26.251-9.366,48.658-28.089,67.237 c-18.731,18.579-41.215,27.868-67.459,27.868c-9.848,0-19.156-1.308-27.923-3.923l-4.185,3.354 c-8.587,6.885-17.154,13.796-25.725,20.702c17.52,8.967,36.86,13.487,58.054,13.487c35.533,0,65.91-12.608,91.124-37.821 c25.214-25.215,37.821-55.584,37.821-91.125c0-35.534-12.607-65.911-37.821-91.126 C981.004,1403.663,977.926,1400.854,974.78,1398.211z\"></path>\n <path fill=\"#F1F2F2\" d=\"M1364.644,1439.619c-4.72,0-8.702,1.624-11.943,4.865c-3.249,3.249-4.866,7.23-4.866,11.944v138.014 l-167.651-211.003c-0.297-0.586-0.74-1.03-1.327-1.326c-4.721-4.714-10.249-7.742-16.588-9.069 c-6.346-1.326-12.608-0.732-18.801,1.77c-6.192,2.509-11.059,6.49-14.598,11.944c-3.539,5.46-5.308,11.577-5.308,18.357v208.348 c0,4.721,1.618,8.703,4.866,11.944c3.241,3.241,7.222,4.865,11.943,4.865c2.945,0,5.751-0.738,8.405-2.211 c2.654-1.472,4.713-3.463,6.193-5.971c1.473-2.503,2.212-5.378,2.212-8.627v-205.251l166.325,209.675 c2.06,2.654,4.423,4.865,7.078,6.635c5.308,3.829,11.349,5.75,18.137,5.75c5.308,0,10.464-1.182,15.482-3.538 c3.539-1.769,6.56-4.127,9.069-7.078c2.502-2.945,4.491-6.338,5.971-10.175c1.473-3.829,2.212-7.664,2.212-11.501v-141.552 c0-4.714-1.624-8.695-4.865-11.944C1373.339,1441.243,1369.359,1439.619,1364.644,1439.619z\"></path>\n <path fill=\"#F1F2F2\" d=\"M1508.406,1432.983c-2.654-1.472-5.46-2.212-8.404-2.212c-4.721,0-8.703,1.7-11.944,5.087 c-3.249,3.395-4.865,7.3-4.865,11.723v163.228c0,4.721,1.616,8.702,4.865,11.943c3.241,3.249,7.223,4.866,11.944,4.866 c2.944,0,5.751-0.732,8.404-2.212c2.655-1.472,4.714-3.539,6.193-6.194c1.473-2.654,2.213-5.453,2.213-8.404V1447.58 c0-2.945-0.74-5.75-2.213-8.405C1513.12,1436.522,1511.06,1434.462,1508.406,1432.983z\"></path>\n <path fill=\"#F1F2F2\" d=\"M1499.78,1367.957c-4.575,0-8.481,1.625-11.722,4.866c-3.249,3.249-4.865,7.23-4.865,11.943 c0,2.951,0.732,5.75,2.212,8.405c1.472,2.654,3.463,4.721,5.971,6.193c2.503,1.479,5.378,2.212,8.627,2.212 c4.423,0,8.328-1.618,11.721-4.865c3.387-3.243,5.088-7.224,5.088-11.944c0-4.713-1.701-8.694-5.088-11.943 C1508.33,1369.582,1504.349,1367.957,1499.78,1367.957z\"></path>\n <path fill=\"#F1F2F2\" d=\"M1859.627,1369.727H1747.27c-35.388,0-65.69,12.607-90.904,37.821 c-25.213,25.215-37.82,55.591-37.82,91.125c0,35.54,12.607,65.911,37.82,91.125c25.215,25.215,55.516,37.821,90.904,37.821h56.178 c4.714,0,8.695-1.618,11.944-4.866c3.241-3.241,4.865-7.222,4.865-11.943c0-4.714-1.624-8.695-4.865-11.943 c-3.249-3.243-7.23-4.866-11.944-4.866h-56.178c-26.251,0-48.659-9.359-67.237-28.09c-18.579-18.723-27.868-41.207-27.868-67.459 c0-26.243,9.29-48.659,27.868-67.237c18.579-18.579,40.987-27.868,67.237-27.868h112.357c4.714,0,8.696-1.693,11.944-5.087 c3.241-3.387,4.865-7.368,4.865-11.943c0-4.569-1.624-8.475-4.865-11.723C1868.322,1371.351,1864.341,1369.727,1859.627,1369.727z \"></path>\n <path fill=\"#06b6d4\" d=\"M2219.256,1371.054h-112.357c-4.423,0-8.336,1.624-11.723,4.865c-3.393,3.249-5.087,7.23-5.087,11.944 c0,4.721,1.694,8.702,5.087,11.943c3.387,3.249,7.3,4.866,11.723,4.866h95.547v95.105c0,26.251-9.365,48.659-28.088,67.237 c-18.731,18.579-41.215,27.868-67.459,27.868c-26.251,0-48.659-9.289-67.237-27.868c-18.579-18.579-27.868-40.987-27.868-67.237 c0-4.713-1.701-8.771-5.088-12.165c-3.393-3.387-7.374-5.087-11.943-5.087c-4.575,0-8.481,1.7-11.722,5.087 c-3.249,3.393-4.865,7.451-4.865,12.165c0,35.388,12.607,65.69,37.82,90.904c25.215,25.213,55.584,37.82,91.126,37.82 c35.532,0,65.91-12.607,91.125-37.82c25.214-25.215,37.82-55.516,37.82-90.904v-111.915c0-4.714-1.624-8.695-4.865-11.944 C2227.951,1372.678,2223.971,1371.054,2219.256,1371.054z\"></path>\n <path fill=\"#06b6d4\" d=\"M2574.24,1502.875c-14.306-14.156-31.483-21.234-51.533-21.234H2410.35 c-10.617,0-19.762-3.829-27.426-11.501c-7.672-7.664-11.501-16.954-11.501-27.868c0-10.907,3.829-20.196,11.501-27.868 c7.664-7.664,16.809-11.501,27.426-11.501h112.357c4.714,0,8.695-1.617,11.944-4.866c3.241-3.241,4.865-7.222,4.865-11.943 c0-4.714-1.624-8.695-4.865-11.944c-3.249-3.241-7.23-4.865-11.944-4.865H2410.35c-20.058,0-37.158,7.154-51.313,21.454 c-14.156,14.308-21.232,31.483-21.232,51.534c0,20.058,7.077,37.234,21.232,51.534c14.156,14.308,31.255,21.454,51.313,21.454 h112.357c7.078,0,13.637,1.77,19.684,5.308c6.042,3.539,10.838,8.336,14.377,14.377c3.538,6.047,5.307,12.607,5.307,19.685 c0,10.616-3.835,19.76-11.501,27.425c-7.672,7.673-16.961,11.502-27.868,11.502h-168.094c-4.721,0-8.703,1.7-11.944,5.087 c-3.249,3.393-4.865,7.374-4.865,11.943c0,4.576,1.616,8.481,4.865,11.723c3.241,3.249,7.223,4.866,11.944,4.866h168.094 c20.051,0,37.227-7.078,51.533-21.234c14.302-14.155,21.454-31.331,21.454-51.534 C2595.695,1534.213,2588.542,1517.03,2574.24,1502.875z\"></path>\n <path fill=\"#06b6d4\" d=\"M854.024,1585.195l20.001-16.028c16.616-13.507,33.04-27.265,50.086-40.251 c1.13-0.861,2.9-1.686,2.003-3.516c-0.843-1.716-2.481-2.302-4.484-2.123c-8.514,0.765-17.016-0.538-25.537-0.353 c-1.124,0.024-2.768,0.221-3.163-1.25c-0.371-1.369,1.088-2.063,1.919-2.894c6.26-6.242,12.574-12.43,18.816-18.691 c9.303-9.327,18.565-18.714,27.851-28.066c1.848-1.859,3.701-3.713,5.549-5.572c2.655-2.661,5.309-5.315,7.958-7.982 c0.574-0.579,1.259-1.141,1.246-1.94c-0.004-0.257-0.078-0.538-0.254-0.853c-0.556-0.981-1.441-1.1-2.469-0.957 c-0.658,0.096-1.315,0.185-1.973,0.275c-3.844,0.538-7.689,1.076-11.533,1.608c-3.641,0.505-7.281,1.02-10.922,1.529 c-4.162,0.582-8.324,1.158-12.486,1.748c-1.142,0.161-2.409,1.662-3.354,0.508c-0.419-0.508-0.431-1.028-0.251-1.531 c0.269-0.741,0.957-1.441,1.387-2.021c3.414-4.58,6.882-9.124,10.356-13.662c1.74-2.272,3.48-4.544,5.214-6.822 c4.682-6.141,9.369-12.281,14.051-18.422c0.09-0.119,0.181-0.237,0.271-0.355c6.848-8.98,13.7-17.958,20.553-26.936 c0.488-0.64,0.977-1.28,1.465-1.92c2.159-2.828,4.315-5.658,6.476-8.486c4.197-5.501,8.454-10.954,12.67-16.442 c0.263-0.347,0.538-0.718,0.717-1.106c0.269-0.586,0.299-1.196-0.335-1.776c-0.825-0.753-1.8-0.15-2.595,0.419 c-0.67,0.472-1.333,0.957-1.955,1.489c-2.206,1.889-4.401,3.797-6.595,5.698c-3.958,3.438-7.922,6.876-11.976,10.194 c-2.443,2.003-4.865,4.028-7.301,6.038c-18.689-10.581-39.53-15.906-62.549-15.906c-35.54,0-65.911,12.607-91.125,37.82 c-25.214,25.215-37.821,55.592-37.821,91.126c0,35.54,12.607,65.91,37.821,91.125c4.146,4.146,8.445,7.916,12.87,11.381 c-9.015,11.14-18.036,22.277-27.034,33.429c-1.208,1.489-3.755,3.151-2.745,4.891c0.078,0.144,0.173,0.281,0.305,0.425 c1.321,1.429,3.492-1.303,4.933-2.457c6.673-5.333,13.333-10.685,19.982-16.042c3.707-2.984,7.417-5.965,11.124-8.952 c1.474-1.188,2.951-2.373,4.425-3.561c6.41-5.164,12.816-10.333,19.238-15.481L854.024,1585.195z M797.552,1498.009 c0-26.243,9.29-48.728,27.868-67.459c18.579-18.723,40.987-28.089,67.238-28.089c12.273,0,23.712,2.075,34.34,6.171 c-3.37,2.905-6.734,5.816-10.069,8.762c-6.075,5.351-12.365,10.469-18.667,15.564c-4.179,3.378-8.371,6.744-12.514,10.164 c-7.54,6.23-15.037,12.52-22.529,18.804c-7.091,5.955-14.182,11.904-21.19,17.949c-1.136,0.974-3.055,1.907-2.135,3.94 c0.831,1.836,2.774,1.417,4.341,1.578l12.145-0.599l14.151-0.698c1.031-0.102,2.192-0.257,2.89,0.632 c0.034,0.044,0.073,0.078,0.106,0.127c1.017,1.561-0.67,2.105-1.387,2.942c-6.308,7.318-12.616,14.637-18.978,21.907 c-8.161,9.339-16.353,18.649-24.544,27.958c-2.146,2.433-4.275,4.879-6.422,7.312c-1.034,1.172-2.129,2.272-1.238,3.922 c0.933,1.728,2.685,1.752,4.323,1.602c4.134-0.367,8.263-0.489,12.396-0.492c0.242,0,0.485-0.005,0.728-0.004 c2.711,0.009,5.422,0.068,8.134,0.145c2.582,0.074,5.166,0.165,7.752,0.249c0.275,1.62-0.879,2.356-1.62,3.259 c-1.333,1.626-2.667,3.247-4,4.867c-4.315,5.252-8.62,10.514-12.928,15.772c-3.562-2.725-7.007-5.733-10.324-9.051 C806.842,1546.667,797.552,1524.26,797.552,1498.009z\"></path>\n </svg>\n </div>\n <h2 class=\"mt-6 text-xl font-medium text-white\">Welcome Back</h2>\n <p class=\"mt-2 text-sm text-zinc-400\">Sign in to your account to continue</p>\n </div>\n\n <!-- Form Container -->\n <div class=\"mt-8 sm:mx-auto sm:w-full sm:max-w-md\">\n <div class=\"bg-zinc-900 shadow-sm ring-1 ring-white/10 rounded-xl px-6 py-8 sm:px-10\">\n <!-- Alerts -->\n ${data.error ? `<div class=\"mb-6\">${renderAlert({ type: 'error', message: data.error })}</div>` : ''}\n ${data.message ? `<div class=\"mb-6\">${renderAlert({ type: 'success', message: data.message })}</div>` : ''}\n\n <!-- Form Response (HTMX target) -->\n <div id=\"form-response\" class=\"mb-6\"></div>\n\n <!-- Form -->\n <form\n id=\"login-form\"\n hx-post=\"/auth/login/form\"\n hx-target=\"#form-response\"\n hx-swap=\"innerHTML\"\n class=\"space-y-6\"\n >\n <!-- Email -->\n <div>\n <label for=\"email\" class=\"block text-sm font-medium text-white mb-2\">\n Email Address\n </label>\n <input\n id=\"email\"\n name=\"email\"\n type=\"email\"\n autocomplete=\"email\"\n required\n class=\"w-full rounded-lg bg-zinc-800 px-3 py-2 text-sm text-white shadow-sm ring-1 ring-inset ring-white/10 placeholder:text-zinc-500 focus:outline-none focus:ring-2 focus:ring-white transition-shadow\"\n placeholder=\"Enter your email\"\n >\n </div>\n\n <!-- Password -->\n <div>\n <label for=\"password\" class=\"block text-sm font-medium text-white mb-2\">\n Password\n </label>\n <input\n id=\"password\"\n name=\"password\"\n type=\"password\"\n autocomplete=\"current-password\"\n required\n class=\"w-full rounded-lg bg-zinc-800 px-3 py-2 text-sm text-white shadow-sm ring-1 ring-inset ring-white/10 placeholder:text-zinc-500 focus:outline-none focus:ring-2 focus:ring-white transition-shadow\"\n placeholder=\"Enter your password\"\n >\n </div>\n\n <!-- Submit Button -->\n <button\n type=\"submit\"\n class=\"w-full rounded-lg bg-white px-4 py-2.5 text-sm font-semibold text-zinc-950 hover:bg-zinc-100 focus:outline-none focus:ring-2 focus:ring-white focus:ring-offset-2 focus:ring-offset-zinc-900 transition-colors\"\n >\n Sign In\n </button>\n </form>\n\n <!-- Links -->\n <div class=\"mt-6 text-center\">\n <p class=\"text-sm text-zinc-400\">\n Don't have an account?\n <a href=\"/auth/register\" class=\"font-semibold text-white hover:text-zinc-300 transition-colors\">Create one here</a>\n </p>\n </div>\n </div>\n\n <!-- Version -->\n <div class=\"mt-6 text-center\">\n <span class=\"inline-flex items-center rounded-md px-2.5 py-1 text-xs font-medium bg-cyan-500/10 text-cyan-400 ring-1 ring-inset ring-cyan-500/20\">\n v${data.version || '0.1.0'}\n </span>\n </div>\n </div>\n </div>\n\n ${demoLoginActive ? `\n <script>\n // Demo Login Prefill Script\n (function() {\n 'use strict';\n\n function prefillLoginForm() {\n const emailInput = document.getElementById('email');\n const passwordInput = document.getElementById('password');\n\n if (emailInput && passwordInput) {\n emailInput.value = 'admin@sonicjs.com';\n passwordInput.value = 'sonicjs!';\n\n // Add visual indication that form is prefilled (only if not already present)\n const form = emailInput.closest('form');\n if (form && !form.querySelector('.demo-mode-notice')) {\n const notice = document.createElement('div');\n notice.className = 'demo-mode-notice mb-6 rounded-lg bg-blue-500/10 p-4 ring-1 ring-blue-500/20';\n notice.innerHTML = '<div class=\"flex items-start gap-x-3\"><svg class=\"h-5 w-5 text-blue-400\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\"><path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z\"/></svg><div><h3 class=\"text-sm font-semibold text-blue-300\">Demo Mode</h3><p class=\"mt-1 text-sm text-blue-400\">Login form prefilled with demo credentials</p></div></div>';\n form.insertBefore(notice, form.firstChild);\n }\n }\n }\n\n // Prefill on page load\n if (document.readyState === 'loading') {\n document.addEventListener('DOMContentLoaded', prefillLoginForm);\n } else {\n prefillLoginForm();\n }\n\n // Also handle HTMX page changes (for SPA-like navigation)\n document.addEventListener('htmx:afterSwap', function(event) {\n if (event.detail.target.id === 'main-content' ||\n document.getElementById('email')) {\n setTimeout(prefillLoginForm, 100);\n }\n });\n })();\n </script>\n ` : ''}\n </body>\n </html>\n `\n}","import { renderAlert } from '../alert.template'\n\nexport interface RegisterPageData {\n error?: string\n}\n\nexport function renderRegisterPage(data: RegisterPageData): string {\n return `\n <!DOCTYPE html>\n <html lang=\"en\" class=\"h-full dark\">\n <head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <title>Register - SonicJS AI</title>\n <link rel=\"icon\" type=\"image/x-icon\" href=\"https://demo.sonicjs.com/images/favicon.ico\">\n <script src=\"https://unpkg.com/htmx.org@2.0.3\"></script>\n <script src=\"https://cdn.tailwindcss.com\"></script>\n <script>\n tailwind.config = {\n darkMode: 'class',\n theme: {\n extend: {}\n }\n }\n </script>\n <style>\n @import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap');\n\n body {\n font-family: 'Inter', system-ui, -apple-system, sans-serif;\n }\n </style>\n </head>\n <body class=\"h-full bg-zinc-950\">\n <div class=\"flex min-h-full flex-col justify-center py-12 sm:px-6 lg:px-8\">\n <!-- Logo Section -->\n <div class=\"sm:mx-auto sm:w-full sm:max-w-md text-center\">\n <div class=\"mx-auto flex h-12 w-12 items-center justify-center rounded-lg bg-white\">\n <svg class=\"h-7 w-7 text-zinc-950\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M13 10V3L4 14h7v7l9-11h-7z\"/>\n </svg>\n </div>\n <h1 class=\"mt-6 text-3xl font-semibold tracking-tight text-white\">SonicJS AI</h1>\n <p class=\"mt-2 text-sm text-zinc-400\">Create your account and get started</p>\n </div>\n\n <!-- Form Container -->\n <div class=\"mt-8 sm:mx-auto sm:w-full sm:max-w-md\">\n <div class=\"bg-zinc-900 shadow-sm ring-1 ring-white/10 rounded-xl px-6 py-8 sm:px-10\">\n <!-- Alerts -->\n ${data.error ? `<div class=\"mb-6\">${renderAlert({ type: 'error', message: data.error })}</div>` : ''}\n\n <!-- Form -->\n <form\n id=\"register-form\"\n hx-post=\"/auth/register/form\"\n hx-target=\"#form-response\"\n hx-swap=\"innerHTML\"\n class=\"space-y-6\"\n >\n <!-- First and Last Name -->\n <div class=\"grid grid-cols-1 sm:grid-cols-2 gap-4\">\n <div>\n <label for=\"firstName\" class=\"block text-sm font-medium text-white mb-2\">\n First Name\n </label>\n <input\n id=\"firstName\"\n name=\"firstName\"\n type=\"text\"\n required\n class=\"w-full rounded-lg bg-zinc-800 px-3 py-2 text-sm text-white shadow-sm ring-1 ring-inset ring-white/10 placeholder:text-zinc-500 focus:outline-none focus:ring-2 focus:ring-white transition-shadow\"\n placeholder=\"First name\"\n >\n </div>\n <div>\n <label for=\"lastName\" class=\"block text-sm font-medium text-white mb-2\">\n Last Name\n </label>\n <input\n id=\"lastName\"\n name=\"lastName\"\n type=\"text\"\n required\n class=\"w-full rounded-lg bg-zinc-800 px-3 py-2 text-sm text-white shadow-sm ring-1 ring-inset ring-white/10 placeholder:text-zinc-500 focus:outline-none focus:ring-2 focus:ring-white transition-shadow\"\n placeholder=\"Last name\"\n >\n </div>\n </div>\n\n <!-- Username -->\n <div>\n <label for=\"username\" class=\"block text-sm font-medium text-white mb-2\">\n Username\n </label>\n <input\n id=\"username\"\n name=\"username\"\n type=\"text\"\n required\n class=\"w-full rounded-lg bg-zinc-800 px-3 py-2 text-sm text-white shadow-sm ring-1 ring-inset ring-white/10 placeholder:text-zinc-500 focus:outline-none focus:ring-2 focus:ring-white transition-shadow\"\n placeholder=\"Choose a username\"\n >\n </div>\n\n <!-- Email -->\n <div>\n <label for=\"email\" class=\"block text-sm font-medium text-white mb-2\">\n Email Address\n </label>\n <input\n id=\"email\"\n name=\"email\"\n type=\"email\"\n autocomplete=\"email\"\n required\n class=\"w-full rounded-lg bg-zinc-800 px-3 py-2 text-sm text-white shadow-sm ring-1 ring-inset ring-white/10 placeholder:text-zinc-500 focus:outline-none focus:ring-2 focus:ring-white transition-shadow\"\n placeholder=\"Enter your email\"\n >\n </div>\n\n <!-- Password -->\n <div>\n <label for=\"password\" class=\"block text-sm font-medium text-white mb-2\">\n Password\n </label>\n <input\n id=\"password\"\n name=\"password\"\n type=\"password\"\n autocomplete=\"new-password\"\n required\n minlength=\"8\"\n class=\"w-full rounded-lg bg-zinc-800 px-3 py-2 text-sm text-white shadow-sm ring-1 ring-inset ring-white/10 placeholder:text-zinc-500 focus:outline-none focus:ring-2 focus:ring-white transition-shadow\"\n placeholder=\"Create a password (min. 8 characters)\"\n >\n </div>\n\n <!-- Submit Button -->\n <button\n type=\"submit\"\n class=\"w-full rounded-lg bg-white px-4 py-2.5 text-sm font-semibold text-zinc-950 hover:bg-zinc-100 focus:outline-none focus:ring-2 focus:ring-white focus:ring-offset-2 focus:ring-offset-zinc-900 transition-colors\"\n >\n Create Account\n </button>\n </form>\n\n <!-- Links -->\n <div class=\"mt-6 text-center\">\n <p class=\"text-sm text-zinc-400\">\n Already have an account?\n <a href=\"/auth/login\" class=\"font-semibold text-white hover:text-zinc-300 transition-colors\">Sign in here</a>\n </p>\n </div>\n\n <div id=\"form-response\"></div>\n </div>\n </div>\n </div>\n </body>\n </html>\n `\n}","/**\n * Auth Validation Service\n *\n * Provides validation schemas for authentication operations\n */\n\nimport { z } from 'zod'\nimport type { D1Database } from '@cloudflare/workers-types'\n\nexport interface AuthSettings {\n enablePasswordLogin?: boolean\n enableOAuthLogin?: boolean\n requireEmailVerification?: boolean\n [key: string]: any\n}\n\n/**\n * Auth Validation Service\n * Provides dynamic validation schemas for registration based on database settings\n */\nconst baseRegistrationSchema = z.object({\n email: z.string().email('Valid email is required'),\n password: z.string().min(8, 'Password must be at least 8 characters'),\n username: z.string().min(3, 'Username must be at least 3 characters').optional(),\n firstName: z.string().min(1, 'First name is required').optional(),\n lastName: z.string().min(1, 'Last name is required').optional()\n})\n\nexport type RegistrationSchema = typeof baseRegistrationSchema\nexport type RegistrationData = z.infer<RegistrationSchema>\n\nexport const authValidationService = {\n /**\n * Build registration schema dynamically based on auth settings\n * For now, returns a static schema with standard fields\n */\n async buildRegistrationSchema(_db: D1Database): Promise<RegistrationSchema> {\n // TODO: Load settings from database to make fields optional/required dynamically\n // For now, use a static schema with common registration fields\n return baseRegistrationSchema\n },\n\n /**\n * Generate default values for optional fields\n */\n generateDefaultValue(field: string, data: any): string {\n switch (field) {\n case 'username':\n // Generate username from email (part before @)\n return data.email ? data.email.split('@')[0] : `user${Date.now()}`\n case 'firstName':\n return 'User'\n case 'lastName':\n return data.email ? data.email.split('@')[0] : 'Account'\n default:\n return ''\n }\n }\n}\n","import { Hono } from 'hono'\n// import { zValidator } from '@hono/zod-validator'\nimport { z } from 'zod'\nimport { setCookie } from 'hono/cookie'\nimport { html } from 'hono/html'\nimport { AuthManager, requireAuth } from '../middleware'\nimport { renderLoginPage, LoginPageData } from '../templates/pages/auth-login.template'\nimport { renderRegisterPage, RegisterPageData } from '../templates/pages/auth-register.template'\nimport { getCacheService, CACHE_CONFIGS } from '../services'\nimport { authValidationService } from '../services/auth-validation'\nimport type { RegistrationData } from '../services/auth-validation'\nimport type { Bindings, Variables } from '../app'\n\nconst authRoutes = new Hono<{ Bindings: Bindings; Variables: Variables }>()\n\n// Login page (HTML form)\nauthRoutes.get('/login', async (c) => {\n const error = c.req.query('error')\n const message = c.req.query('message')\n \n const pageData: LoginPageData = {\n error: error || undefined,\n message: message || undefined,\n version: c.get('appVersion')\n }\n \n // Check if demo login plugin is active\n const db = c.env.DB\n let demoLoginActive = false\n try {\n const plugin = await db.prepare('SELECT * FROM plugins WHERE id = ? AND status = ?')\n .bind('demo-login-prefill', 'active')\n .first()\n demoLoginActive = !!plugin\n } catch (error) {\n // Ignore database errors - plugin system might not be initialized\n }\n \n return c.html(renderLoginPage(pageData, demoLoginActive))\n})\n\n// Registration page (HTML form)\nauthRoutes.get('/register', (c) => {\n const error = c.req.query('error')\n \n const pageData: RegisterPageData = {\n error: error || undefined\n }\n \n return c.html(renderRegisterPage(pageData))\n})\n\n// Login schema\nconst loginSchema = z.object({\n email: z.string().email('Valid email is required'),\n password: z.string().min(1, 'Password is required')\n})\n\n// Register new user\nauthRoutes.post('/register',\n async (c) => {\n try {\n const db = c.env.DB\n\n // Parse JSON with error handling\n let requestData\n try {\n requestData = await c.req.json()\n } catch (parseError) {\n return c.json({ error: 'Invalid JSON in request body' }, 400)\n }\n\n // Build and validate using dynamic schema\n const validationSchema = await authValidationService.buildRegistrationSchema(db)\n\n let validatedData: RegistrationData\n try {\n validatedData = await validationSchema.parseAsync(requestData)\n } catch (validationError: any) {\n return c.json({\n error: 'Validation failed',\n details: validationError.issues?.map((e: any) => e.message) || [validationError.message || 'Invalid request data']\n }, 400)\n }\n\n // Extract fields with defaults for optional ones\n const email = validatedData.email\n const password = validatedData.password\n const username = validatedData.username || authValidationService.generateDefaultValue('username', validatedData)\n const firstName = validatedData.firstName || authValidationService.generateDefaultValue('firstName', validatedData)\n const lastName = validatedData.lastName || authValidationService.generateDefaultValue('lastName', validatedData)\n\n // Normalize email to lowercase\n const normalizedEmail = email.toLowerCase()\n \n // Check if user already exists\n const existingUser = await db.prepare('SELECT id FROM users WHERE email = ? OR username = ?')\n .bind(normalizedEmail, username)\n .first()\n \n if (existingUser) {\n return c.json({ error: 'User with this email or username already exists' }, 400)\n }\n \n // Hash password\n const passwordHash = await AuthManager.hashPassword(password)\n \n // Create user\n const userId = crypto.randomUUID()\n const now = new Date()\n \n await db.prepare(`\n INSERT INTO users (id, email, username, first_name, last_name, password_hash, role, is_active, created_at, updated_at)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n `).bind(\n userId,\n normalizedEmail,\n username,\n firstName,\n lastName,\n passwordHash,\n 'viewer', // Default role\n 1, // is_active\n now.getTime(),\n now.getTime()\n ).run()\n \n // Generate JWT token\n const token = await AuthManager.generateToken(userId, normalizedEmail, 'viewer')\n \n // Set HTTP-only cookie\n setCookie(c, 'auth_token', token, {\n httpOnly: true,\n secure: true,\n sameSite: 'Strict',\n maxAge: 60 * 60 * 24 // 24 hours\n })\n \n return c.json({\n user: {\n id: userId,\n email: normalizedEmail,\n username,\n firstName,\n lastName,\n role: 'viewer'\n },\n token\n }, 201)\n } catch (error) {\n console.error('Registration error:', error)\n // Return validation errors as 400, other errors as 500\n if (error instanceof Error && error.message.includes('validation')) {\n return c.json({ error: error.message }, 400)\n }\n return c.json({\n error: 'Registration failed',\n details: error instanceof Error ? error.message : String(error)\n }, 500)\n }\n }\n)\n\n// Login user\nauthRoutes.post('/login', async (c) => {\n try {\n const body = await c.req.json()\n const validation = loginSchema.safeParse(body)\n if (!validation.success) {\n return c.json({ error: 'Validation failed', details: validation.error.issues }, 400)\n }\n const { email, password } = validation.data\n const db = c.env.DB\n \n // Normalize email to lowercase\n const normalizedEmail = email.toLowerCase()\n \n // Find user with caching\n const cache = getCacheService(CACHE_CONFIGS.user!)\n let user = await cache.get<any>(cache.generateKey('user', `email:${normalizedEmail}`))\n\n if (!user) {\n user = await db.prepare('SELECT * FROM users WHERE email = ? AND is_active = 1')\n .bind(normalizedEmail)\n .first() as any\n\n if (user) {\n // Cache the user for faster subsequent lookups\n await cache.set(cache.generateKey('user', `email:${normalizedEmail}`), user)\n await cache.set(cache.generateKey('user', user.id), user)\n }\n }\n\n if (!user) {\n return c.json({ error: 'Invalid email or password' }, 401)\n }\n \n // Verify password\n const isValidPassword = await AuthManager.verifyPassword(password, user.password_hash)\n if (!isValidPassword) {\n return c.json({ error: 'Invalid email or password' }, 401)\n }\n \n // Generate JWT token\n const token = await AuthManager.generateToken(user.id, user.email, user.role)\n \n // Set HTTP-only cookie\n setCookie(c, 'auth_token', token, {\n httpOnly: true,\n secure: true,\n sameSite: 'Strict',\n maxAge: 60 * 60 * 24 // 24 hours\n })\n \n // Update last login\n await db.prepare('UPDATE users SET last_login_at = ? WHERE id = ?')\n .bind(new Date().getTime(), user.id)\n .run()\n\n // Invalidate user cache on login\n await cache.delete(cache.generateKey('user', user.id))\n await cache.delete(cache.generateKey('user', `email:${normalizedEmail}`))\n\n return c.json({\n user: {\n id: user.id,\n email: user.email,\n username: user.username,\n firstName: user.first_name,\n lastName: user.last_name,\n role: user.role\n },\n token\n })\n } catch (error) {\n console.error('Login error:', error)\n return c.json({ error: 'Login failed' }, 500)\n }\n})\n\n// Logout user (both GET and POST for convenience)\nauthRoutes.post('/logout', (c) => {\n // Clear the auth cookie\n setCookie(c, 'auth_token', '', {\n httpOnly: true,\n secure: false, // Set to true in production with HTTPS\n sameSite: 'Strict',\n maxAge: 0 // Expire immediately\n })\n \n return c.json({ message: 'Logged out successfully' })\n})\n\nauthRoutes.get('/logout', (c) => {\n // Clear the auth cookie\n setCookie(c, 'auth_token', '', {\n httpOnly: true,\n secure: false, // Set to true in production with HTTPS\n sameSite: 'Strict',\n maxAge: 0 // Expire immediately\n })\n \n return c.redirect('/auth/login?message=You have been logged out successfully')\n})\n\n// Get current user\nauthRoutes.get('/me', requireAuth(), async (c) => {\n try {\n // This would need the auth middleware applied\n const user = c.get('user')\n \n if (!user) {\n return c.json({ error: 'Not authenticated' }, 401)\n }\n \n const db = c.env.DB\n const userData = await db.prepare('SELECT id, email, username, first_name, last_name, role, created_at FROM users WHERE id = ?')\n .bind(user.userId)\n .first()\n \n if (!userData) {\n return c.json({ error: 'User not found' }, 404)\n }\n \n return c.json({ user: userData })\n } catch (error) {\n console.error('Get user error:', error)\n return c.json({ error: 'Failed to get user' }, 500)\n }\n})\n\n// Refresh token\nauthRoutes.post('/refresh', requireAuth(), async (c) => {\n try {\n const user = c.get('user')\n \n if (!user) {\n return c.json({ error: 'Not authenticated' }, 401)\n }\n \n // Generate new token\n const token = await AuthManager.generateToken(user.userId, user.email, user.role)\n \n // Set new cookie\n setCookie(c, 'auth_token', token, {\n httpOnly: true,\n secure: true,\n sameSite: 'Strict',\n maxAge: 60 * 60 * 24 // 24 hours\n })\n \n return c.json({ token })\n } catch (error) {\n console.error('Token refresh error:', error)\n return c.json({ error: 'Token refresh failed' }, 500)\n }\n})\n\n// Form-based registration handler (for HTML forms)\nauthRoutes.post('/register/form', async (c) => {\n try {\n const db = c.env.DB\n const formData = await c.req.formData()\n\n // Extract form data\n const requestData = {\n email: formData.get('email') as string,\n password: formData.get('password') as string,\n username: formData.get('username') as string,\n firstName: formData.get('firstName') as string,\n lastName: formData.get('lastName') as string,\n }\n\n // Normalize email to lowercase\n const normalizedEmail = requestData.email?.toLowerCase()\n requestData.email = normalizedEmail\n\n // Build and validate using dynamic schema\n const validationSchema = await authValidationService.buildRegistrationSchema(db)\n const validation = await validationSchema.safeParseAsync(requestData)\n\n if (!validation.success) {\n return c.html(html`\n <div class=\"bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded\">\n ${validation.error.issues.map((err: { message: string }) => err.message).join(', ')}\n </div>\n `)\n }\n\n const validatedData: RegistrationData = validation.data\n\n // Extract fields with defaults for optional ones\n // const email = validatedData.email\n const password = validatedData.password\n const username = validatedData.username || authValidationService.generateDefaultValue('username', validatedData)\n const firstName = validatedData.firstName || authValidationService.generateDefaultValue('firstName', validatedData)\n const lastName = validatedData.lastName || authValidationService.generateDefaultValue('lastName', validatedData)\n \n // Check if user already exists\n const existingUser = await db.prepare('SELECT id FROM users WHERE email = ? OR username = ?')\n .bind(normalizedEmail, username)\n .first()\n \n if (existingUser) {\n return c.html(html`\n <div class=\"bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded\">\n User with this email or username already exists\n </div>\n `)\n }\n \n // Hash password\n const passwordHash = await AuthManager.hashPassword(password)\n \n // Create user\n const userId = crypto.randomUUID()\n const now = new Date()\n \n await db.prepare(`\n INSERT INTO users (id, email, username, first_name, last_name, password_hash, role, is_active, created_at, updated_at)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n `).bind(\n userId,\n normalizedEmail,\n username,\n firstName,\n lastName,\n passwordHash,\n 'admin', // First user gets admin role\n 1, // is_active\n now.getTime(),\n now.getTime()\n ).run()\n \n // Generate JWT token\n const token = await AuthManager.generateToken(userId, normalizedEmail, 'admin')\n \n // Set HTTP-only cookie\n setCookie(c, 'auth_token', token, {\n httpOnly: true,\n secure: false, // Set to true in production with HTTPS\n sameSite: 'Strict',\n maxAge: 60 * 60 * 24 // 24 hours\n })\n \n return c.html(html`\n <div class=\"bg-green-100 border border-green-400 text-green-700 px-4 py-3 rounded\">\n Account created successfully! Redirecting to admin dashboard...\n <script>\n setTimeout(() => {\n window.location.href = '/admin/dashboard';\n }, 2000);\n </script>\n </div>\n `)\n } catch (error) {\n console.error('Registration error:', error)\n return c.html(html`\n <div class=\"bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded\">\n Registration failed. Please try again.\n </div>\n `)\n }\n})\n\n// Form-based login handler (for HTML forms)\nauthRoutes.post('/login/form', async (c) => {\n try {\n const formData = await c.req.formData()\n const email = formData.get('email') as string\n const password = formData.get('password') as string\n\n // Normalize email to lowercase\n const normalizedEmail = email.toLowerCase()\n\n // Validate the data\n const validation = loginSchema.safeParse({ email: normalizedEmail, password })\n\n if (!validation.success) {\n return c.html(html`\n <div class=\"bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded\">\n ${validation.error.issues.map((err: { message: string }) => err.message).join(', ')}\n </div>\n `)\n }\n\n const db = c.env.DB\n \n // Find user\n const user = await db.prepare('SELECT * FROM users WHERE email = ? AND is_active = 1')\n .bind(normalizedEmail)\n .first() as any\n \n if (!user) {\n return c.html(html`\n <div class=\"bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded\">\n Invalid email or password\n </div>\n `)\n }\n \n // Verify password\n const isValidPassword = await AuthManager.verifyPassword(password, user.password_hash)\n if (!isValidPassword) {\n return c.html(html`\n <div class=\"bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded\">\n Invalid email or password\n </div>\n `)\n }\n \n // Generate JWT token\n const token = await AuthManager.generateToken(user.id, user.email, user.role)\n \n // Set HTTP-only cookie\n setCookie(c, 'auth_token', token, {\n httpOnly: true,\n secure: false, // Set to true in production with HTTPS\n sameSite: 'Strict',\n maxAge: 60 * 60 * 24 // 24 hours\n })\n \n // Update last login\n await db.prepare('UPDATE users SET last_login_at = ? WHERE id = ?')\n .bind(new Date().getTime(), user.id)\n .run()\n \n return c.html(html`\n <div id=\"form-response\">\n <div class=\"rounded-lg bg-green-100 dark:bg-lime-500/10 p-4 ring-1 ring-green-400 dark:ring-lime-500/20\">\n <div class=\"flex items-start gap-x-3\">\n <svg class=\"h-5 w-5 text-green-600 dark:text-lime-400 shrink-0\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z\"/>\n </svg>\n <div class=\"flex-1\">\n <p class=\"text-sm font-medium text-green-700 dark:text-lime-300\">Login successful! Redirecting to admin dashboard...</p>\n </div>\n </div>\n <script>\n setTimeout(() => {\n window.location.href = '/admin/dashboard';\n }, 2000);\n </script>\n </div>\n </div>\n `)\n } catch (error) {\n console.error('Login error:', error)\n return c.html(html`\n <div class=\"bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded\">\n Login failed. Please try again.\n </div>\n `)\n }\n})\n\n// Test seeding endpoint (only for development/testing)\nauthRoutes.post('/seed-admin', async (c) => {\n try {\n const db = c.env.DB\n \n // First ensure the users table exists\n await db.prepare(`\n CREATE TABLE IF NOT EXISTS users (\n id TEXT PRIMARY KEY,\n email TEXT NOT NULL UNIQUE,\n username TEXT NOT NULL UNIQUE,\n first_name TEXT NOT NULL,\n last_name TEXT NOT NULL,\n password_hash TEXT,\n role TEXT NOT NULL DEFAULT 'viewer',\n avatar TEXT,\n is_active INTEGER NOT NULL DEFAULT 1,\n last_login_at INTEGER,\n created_at INTEGER NOT NULL,\n updated_at INTEGER NOT NULL\n )\n `).run()\n \n // Check if admin user already exists\n const existingAdmin = await db.prepare('SELECT id FROM users WHERE email = ? OR username = ?')\n .bind('admin@sonicjs.com', 'admin')\n .first()\n\n if (existingAdmin) {\n // Update the password to ensure it's correct for testing\n const passwordHash = await AuthManager.hashPassword('sonicjs!')\n await db.prepare('UPDATE users SET password_hash = ?, updated_at = ? WHERE id = ?')\n .bind(passwordHash, Date.now(), existingAdmin.id)\n .run()\n\n return c.json({\n message: 'Admin user already exists (password updated)',\n user: {\n id: existingAdmin.id,\n email: 'admin@sonicjs.com',\n username: 'admin',\n role: 'admin'\n }\n })\n }\n\n // Hash password\n const passwordHash = await AuthManager.hashPassword('sonicjs!')\n \n // Create admin user\n const userId = 'admin-user-id'\n const now = Date.now()\n const adminEmail = 'admin@sonicjs.com'.toLowerCase()\n \n await db.prepare(`\n INSERT INTO users (id, email, username, first_name, last_name, password_hash, role, is_active, created_at, updated_at)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n `).bind(\n userId,\n adminEmail,\n 'admin',\n 'Admin',\n 'User',\n passwordHash,\n 'admin',\n 1, // is_active\n now,\n now\n ).run()\n \n return c.json({ \n message: 'Admin user created successfully',\n user: {\n id: userId,\n email: adminEmail,\n username: 'admin',\n role: 'admin'\n },\n passwordHash: passwordHash // For debugging\n })\n } catch (error) {\n console.error('Seed admin error:', error)\n return c.json({ error: 'Failed to create admin user', details: error instanceof Error ? error.message : String(error) }, 500)\n }\n})\n\n\n// Accept invitation page\nauthRoutes.get('/accept-invitation', async (c) => {\n try {\n const token = c.req.query('token')\n \n if (!token) {\n return c.html(`\n <html>\n <head><title>Invalid Invitation</title></head>\n <body>\n <h1>Invalid Invitation</h1>\n <p>The invitation link is invalid or has expired.</p>\n <a href=\"/auth/login\">Go to Login</a>\n </body>\n </html>\n `)\n }\n\n const db = c.env.DB\n \n // Check if invitation token is valid\n const userStmt = db.prepare(`\n SELECT id, email, first_name, last_name, role, invited_at\n FROM users \n WHERE invitation_token = ? AND is_active = 0\n `)\n const invitedUser = await userStmt.bind(token).first() as any\n\n if (!invitedUser) {\n return c.html(`\n <html>\n <head><title>Invalid Invitation</title></head>\n <body>\n <h1>Invalid Invitation</h1>\n <p>The invitation link is invalid or has expired.</p>\n <a href=\"/auth/login\">Go to Login</a>\n </body>\n </html>\n `)\n }\n\n // Check if invitation is expired (7 days)\n const invitationAge = Date.now() - invitedUser.invited_at\n const maxAge = 7 * 24 * 60 * 60 * 1000 // 7 days\n \n if (invitationAge > maxAge) {\n return c.html(`\n <html>\n <head><title>Invitation Expired</title></head>\n <body>\n <h1>Invitation Expired</h1>\n <p>This invitation has expired. Please contact your administrator for a new invitation.</p>\n <a href=\"/auth/login\">Go to Login</a>\n </body>\n </html>\n `)\n }\n\n // Show invitation acceptance form\n return c.html(`\n <!DOCTYPE html>\n <html lang=\"en\">\n <head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <title>Accept Invitation - SonicJS AI</title>\n <script src=\"https://cdn.tailwindcss.com\"></script>\n <style>\n body {\n background: linear-gradient(135deg, #1e293b 0%, #0f172a 100%);\n min-height: 100vh;\n }\n </style>\n </head>\n <body class=\"bg-gray-900 text-white\">\n <div class=\"min-h-screen flex items-center justify-center px-4\">\n <div class=\"max-w-md w-full space-y-8\">\n <div class=\"text-center\">\n <div class=\"mx-auto w-16 h-16 bg-blue-600 rounded-2xl flex items-center justify-center mb-6\">\n <svg class=\"w-8 h-8 text-white\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M18 9v3m0 0v3m0-3h3m-3 0h-3m-2-5a4 4 0 11-8 0 4 4 0 018 0zM3 20a6 6 0 0112 0v1H3v-1z\"/>\n </svg>\n </div>\n <h2 class=\"text-3xl font-bold\">Accept Invitation</h2>\n <p class=\"mt-2 text-gray-400\">Complete your account setup</p>\n <p class=\"mt-4 text-sm\">\n You've been invited as <strong>${invitedUser.first_name} ${invitedUser.last_name}</strong><br>\n <span class=\"text-gray-400\">${invitedUser.email}</span><br>\n <span class=\"text-blue-400 capitalize\">${invitedUser.role}</span>\n </p>\n </div>\n\n <form method=\"POST\" action=\"/auth/accept-invitation\" class=\"mt-8 space-y-6\">\n <input type=\"hidden\" name=\"token\" value=\"${token}\" />\n \n <div>\n <label class=\"block text-sm font-medium text-gray-300 mb-2\">Username</label>\n <input \n type=\"text\" \n name=\"username\" \n required\n class=\"w-full px-4 py-3 bg-gray-800 border border-gray-700 rounded-xl text-white focus:outline-none focus:border-blue-500 focus:ring-2 focus:ring-blue-500 transition-all\"\n placeholder=\"Enter your username\"\n >\n </div>\n\n <div>\n <label class=\"block text-sm font-medium text-gray-300 mb-2\">Password</label>\n <input \n type=\"password\" \n name=\"password\" \n required\n minlength=\"8\"\n class=\"w-full px-4 py-3 bg-gray-800 border border-gray-700 rounded-xl text-white focus:outline-none focus:border-blue-500 focus:ring-2 focus:ring-blue-500 transition-all\"\n placeholder=\"Enter your password\"\n >\n <p class=\"text-xs text-gray-400 mt-1\">Password must be at least 8 characters long</p>\n </div>\n\n <div>\n <label class=\"block text-sm font-medium text-gray-300 mb-2\">Confirm Password</label>\n <input \n type=\"password\" \n name=\"confirm_password\" \n required\n minlength=\"8\"\n class=\"w-full px-4 py-3 bg-gray-800 border border-gray-700 rounded-xl text-white focus:outline-none focus:border-blue-500 focus:ring-2 focus:ring-blue-500 transition-all\"\n placeholder=\"Confirm your password\"\n >\n </div>\n\n <button \n type=\"submit\"\n class=\"w-full py-3 px-4 bg-gradient-to-r from-blue-600 to-purple-600 text-white font-semibold rounded-xl hover:from-blue-700 hover:to-purple-700 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 focus:ring-offset-gray-900 transition-all\"\n >\n Accept Invitation & Create Account\n </button>\n </form>\n </div>\n </div>\n </body>\n </html>\n `)\n\n } catch (error) {\n console.error('Accept invitation page error:', error)\n return c.html(`\n <html>\n <head><title>Error</title></head>\n <body>\n <h1>Error</h1>\n <p>An error occurred while processing your invitation.</p>\n <a href=\"/auth/login\">Go to Login</a>\n </body>\n </html>\n `)\n }\n})\n\n// Process invitation acceptance\nauthRoutes.post('/accept-invitation', async (c) => {\n try {\n const formData = await c.req.formData()\n const token = formData.get('token')?.toString()\n const username = formData.get('username')?.toString()?.trim()\n const password = formData.get('password')?.toString()\n const confirmPassword = formData.get('confirm_password')?.toString()\n\n if (!token || !username || !password || !confirmPassword) {\n return c.json({ error: 'All fields are required' }, 400)\n }\n\n if (password !== confirmPassword) {\n return c.json({ error: 'Passwords do not match' }, 400)\n }\n\n if (password.length < 8) {\n return c.json({ error: 'Password must be at least 8 characters long' }, 400)\n }\n\n const db = c.env.DB\n\n // Check if invitation token is valid\n const userStmt = db.prepare(`\n SELECT id, email, first_name, last_name, role, invited_at\n FROM users \n WHERE invitation_token = ? AND is_active = 0\n `)\n const invitedUser = await userStmt.bind(token).first() as any\n\n if (!invitedUser) {\n return c.json({ error: 'Invalid or expired invitation' }, 400)\n }\n\n // Check if invitation is expired (7 days)\n const invitationAge = Date.now() - invitedUser.invited_at\n const maxAge = 7 * 24 * 60 * 60 * 1000 // 7 days\n \n if (invitationAge > maxAge) {\n return c.json({ error: 'Invitation has expired' }, 400)\n }\n\n // Check if username is available\n const existingUsernameStmt = db.prepare(`\n SELECT id FROM users WHERE username = ? AND id != ?\n `)\n const existingUsername = await existingUsernameStmt.bind(username, invitedUser.id).first()\n\n if (existingUsername) {\n return c.json({ error: 'Username is already taken' }, 400)\n }\n\n // Hash password\n const passwordHash = await AuthManager.hashPassword(password)\n\n // Activate user account\n const updateStmt = db.prepare(`\n UPDATE users SET \n username = ?,\n password_hash = ?,\n is_active = 1,\n email_verified = 1,\n invitation_token = NULL,\n accepted_invitation_at = ?,\n updated_at = ?\n WHERE id = ?\n `)\n\n await updateStmt.bind(\n username,\n passwordHash,\n Date.now(),\n Date.now(),\n invitedUser.id\n ).run()\n\n // Generate JWT token for auto-login\n const authToken = await AuthManager.generateToken(invitedUser.id, invitedUser.email, invitedUser.role)\n \n // Set HTTP-only cookie\n setCookie(c, 'auth_token', authToken, {\n httpOnly: true,\n secure: true,\n sameSite: 'Strict',\n maxAge: 60 * 60 * 24 // 24 hours\n })\n\n // Log the activity (TODO: implement activity logging)\n // Activity logging is deferred until utils/log-activity is implemented\n\n // Redirect to admin dashboard\n return c.redirect('/admin/dashboard?welcome=true')\n\n } catch (error) {\n console.error('Accept invitation error:', error)\n return c.json({ error: 'Failed to accept invitation' }, 500)\n }\n})\n\n// Request password reset\nauthRoutes.post('/request-password-reset', async (c) => {\n try {\n const formData = await c.req.formData()\n const email = formData.get('email')?.toString()?.trim()?.toLowerCase()\n\n if (!email) {\n return c.json({ error: 'Email is required' }, 400)\n }\n\n // Validate email format\n const emailRegex = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/\n if (!emailRegex.test(email)) {\n return c.json({ error: 'Please enter a valid email address' }, 400)\n }\n\n const db = c.env.DB\n\n // Check if user exists and is active\n const userStmt = db.prepare(`\n SELECT id, email, first_name, last_name FROM users \n WHERE email = ? AND is_active = 1\n `)\n const user = await userStmt.bind(email).first() as any\n\n // Always return success to prevent email enumeration\n if (!user) {\n return c.json({\n success: true,\n message: 'If an account with this email exists, a password reset link has been sent.'\n })\n }\n\n // Generate password reset token (expires in 1 hour)\n const resetToken = crypto.randomUUID()\n const resetExpires = Date.now() + (60 * 60 * 1000) // 1 hour\n\n // Update user with reset token\n const updateStmt = db.prepare(`\n UPDATE users SET \n password_reset_token = ?,\n password_reset_expires = ?,\n updated_at = ?\n WHERE id = ?\n `)\n\n await updateStmt.bind(\n resetToken,\n resetExpires,\n Date.now(),\n user.id\n ).run()\n\n // Log the activity (TODO: implement activity logging)\n // Activity logging is deferred until utils/log-activity is implemented\n\n // In a real implementation, you would send an email here\n // For now, we'll return the reset link for development\n const resetLink = `${c.req.header('origin') || 'http://localhost:8787'}/auth/reset-password?token=${resetToken}`\n\n return c.json({\n success: true,\n message: 'If an account with this email exists, a password reset link has been sent.',\n reset_link: resetLink // In production, this would be sent via email\n })\n\n } catch (error) {\n console.error('Password reset request error:', error)\n return c.json({ error: 'Failed to process password reset request' }, 500)\n }\n})\n\n// Show password reset form\nauthRoutes.get('/reset-password', async (c) => {\n try {\n const token = c.req.query('token')\n \n if (!token) {\n return c.html(`\n <html>\n <head><title>Invalid Reset Link</title></head>\n <body>\n <h1>Invalid Reset Link</h1>\n <p>The password reset link is invalid or has expired.</p>\n <a href=\"/auth/login\">Go to Login</a>\n </body>\n </html>\n `)\n }\n\n const db = c.env.DB\n \n // Check if reset token is valid and not expired\n const userStmt = db.prepare(`\n SELECT id, email, first_name, last_name, password_reset_expires\n FROM users \n WHERE password_reset_token = ? AND is_active = 1\n `)\n const user = await userStmt.bind(token).first() as any\n\n if (!user) {\n return c.html(`\n <html>\n <head><title>Invalid Reset Link</title></head>\n <body>\n <h1>Invalid Reset Link</h1>\n <p>The password reset link is invalid or has already been used.</p>\n <a href=\"/auth/login\">Go to Login</a>\n </body>\n </html>\n `)\n }\n\n // Check if token is expired\n if (Date.now() > user.password_reset_expires) {\n return c.html(`\n <html>\n <head><title>Reset Link Expired</title></head>\n <body>\n <h1>Reset Link Expired</h1>\n <p>The password reset link has expired. Please request a new one.</p>\n <a href=\"/auth/login\">Go to Login</a>\n </body>\n </html>\n `)\n }\n\n // Show password reset form\n return c.html(`\n <!DOCTYPE html>\n <html lang=\"en\">\n <head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <title>Reset Password - SonicJS AI</title>\n <script src=\"https://cdn.tailwindcss.com\"></script>\n <style>\n body {\n background: linear-gradient(135deg, #1e293b 0%, #0f172a 100%);\n min-height: 100vh;\n }\n </style>\n </head>\n <body class=\"bg-gray-900 text-white\">\n <div class=\"min-h-screen flex items-center justify-center px-4\">\n <div class=\"max-w-md w-full space-y-8\">\n <div class=\"text-center\">\n <div class=\"mx-auto w-16 h-16 bg-blue-600 rounded-2xl flex items-center justify-center mb-6\">\n <svg class=\"w-8 h-8 text-white\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M15 7a2 2 0 012 2m4 0a6 6 0 01-7.743 5.743L11 17H9v2H7v2H4a1 1 0 01-1-1v-3.586l4.293-4.293A6 6 0 0119 9z\"/>\n </svg>\n </div>\n <h2 class=\"text-3xl font-bold\">Reset Password</h2>\n <p class=\"mt-2 text-gray-400\">Choose a new password for your account</p>\n <p class=\"mt-4 text-sm\">\n Reset password for <strong>${user.first_name} ${user.last_name}</strong><br>\n <span class=\"text-gray-400\">${user.email}</span>\n </p>\n </div>\n\n <form method=\"POST\" action=\"/auth/reset-password\" class=\"mt-8 space-y-6\">\n <input type=\"hidden\" name=\"token\" value=\"${token}\" />\n \n <div>\n <label class=\"block text-sm font-medium text-gray-300 mb-2\">New Password</label>\n <input \n type=\"password\" \n name=\"password\" \n required\n minlength=\"8\"\n class=\"w-full px-4 py-3 bg-gray-800 border border-gray-700 rounded-xl text-white focus:outline-none focus:border-blue-500 focus:ring-2 focus:ring-blue-500 transition-all\"\n placeholder=\"Enter your new password\"\n >\n <p class=\"text-xs text-gray-400 mt-1\">Password must be at least 8 characters long</p>\n </div>\n\n <div>\n <label class=\"block text-sm font-medium text-gray-300 mb-2\">Confirm New Password</label>\n <input \n type=\"password\" \n name=\"confirm_password\" \n required\n minlength=\"8\"\n class=\"w-full px-4 py-3 bg-gray-800 border border-gray-700 rounded-xl text-white focus:outline-none focus:border-blue-500 focus:ring-2 focus:ring-blue-500 transition-all\"\n placeholder=\"Confirm your new password\"\n >\n </div>\n\n <button \n type=\"submit\"\n class=\"w-full py-3 px-4 bg-gradient-to-r from-blue-600 to-purple-600 text-white font-semibold rounded-xl hover:from-blue-700 hover:to-purple-700 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 focus:ring-offset-gray-900 transition-all\"\n >\n Reset Password\n </button>\n </form>\n\n <div class=\"text-center\">\n <a href=\"/auth/login\" class=\"text-sm text-blue-400 hover:text-blue-300\">\n Back to Login\n </a>\n </div>\n </div>\n </div>\n </body>\n </html>\n `)\n\n } catch (error) {\n console.error('Password reset page error:', error)\n return c.html(`\n <html>\n <head><title>Error</title></head>\n <body>\n <h1>Error</h1>\n <p>An error occurred while processing your password reset.</p>\n <a href=\"/auth/login\">Go to Login</a>\n </body>\n </html>\n `)\n }\n})\n\n// Process password reset\nauthRoutes.post('/reset-password', async (c) => {\n try {\n const formData = await c.req.formData()\n const token = formData.get('token')?.toString()\n const password = formData.get('password')?.toString()\n const confirmPassword = formData.get('confirm_password')?.toString()\n\n if (!token || !password || !confirmPassword) {\n return c.json({ error: 'All fields are required' }, 400)\n }\n\n if (password !== confirmPassword) {\n return c.json({ error: 'Passwords do not match' }, 400)\n }\n\n if (password.length < 8) {\n return c.json({ error: 'Password must be at least 8 characters long' }, 400)\n }\n\n const db = c.env.DB\n\n // Check if reset token is valid and not expired\n const userStmt = db.prepare(`\n SELECT id, email, password_hash, password_reset_expires\n FROM users\n WHERE password_reset_token = ? AND is_active = 1\n `)\n const user = await userStmt.bind(token).first() as any\n\n if (!user) {\n return c.json({ error: 'Invalid or expired reset token' }, 400)\n }\n\n // Check if token is expired\n if (Date.now() > user.password_reset_expires) {\n return c.json({ error: 'Reset token has expired' }, 400)\n }\n\n // Hash new password\n const newPasswordHash = await AuthManager.hashPassword(password)\n\n // Store old password in history (skip if table doesn't exist)\n try {\n const historyStmt = db.prepare(`\n INSERT INTO password_history (id, user_id, password_hash, created_at)\n VALUES (?, ?, ?, ?)\n `)\n await historyStmt.bind(\n crypto.randomUUID(),\n user.id,\n user.password_hash,\n Date.now()\n ).run()\n } catch (historyError) {\n // Password history table may not exist yet\n console.warn('Could not store password history:', historyError)\n }\n\n // Update user password and clear reset token\n const updateStmt = db.prepare(`\n UPDATE users SET\n password_hash = ?,\n password_reset_token = NULL,\n password_reset_expires = NULL,\n updated_at = ?\n WHERE id = ?\n `)\n\n await updateStmt.bind(\n newPasswordHash,\n Date.now(),\n user.id\n ).run()\n\n // Log the activity (TODO: implement activity logging)\n // Activity logging is deferred until utils/log-activity is implemented\n\n // Redirect to login with success message\n return c.redirect('/auth/login?message=Password reset successfully. Please log in with your new password.')\n\n } catch (error) {\n console.error('Password reset error:', error)\n return c.json({ error: 'Failed to reset password' }, 500)\n }\n})\n\nexport default authRoutes\n","/**\n * Test Cleanup Routes\n *\n * Provides endpoints to clean up test data after e2e tests\n * WARNING: These endpoints should only be available in development/test environments\n */\n\nimport { Hono } from 'hono'\nimport type { Context } from 'hono'\nimport type { D1Database } from '@cloudflare/workers-types'\n\nconst app = new Hono()\n\n/**\n * Clean up all test data (collections, content, users except admin)\n * POST /test-cleanup\n */\napp.post('/test-cleanup', async (c: Context) => {\n const db = c.env.DB as D1Database\n\n // Only allow in development/test environments\n if (c.env.ENVIRONMENT === 'production') {\n return c.json({ error: 'Cleanup endpoint not available in production' }, 403)\n }\n\n try {\n let deletedCount = 0\n\n // Use pattern-based deletes to avoid SQL variable limits\n // This approach uses subqueries instead of building large IN lists\n\n // Step 1: Delete child data for test content (by pattern)\n await db.prepare(`\n DELETE FROM content_versions\n WHERE content_id IN (\n SELECT id FROM content\n WHERE title LIKE 'Test %' OR title LIKE '%E2E%' OR title LIKE '%Playwright%' OR title LIKE '%Sample%'\n )\n `).run()\n\n await db.prepare(`\n DELETE FROM workflow_history\n WHERE content_id IN (\n SELECT id FROM content\n WHERE title LIKE 'Test %' OR title LIKE '%E2E%' OR title LIKE '%Playwright%' OR title LIKE '%Sample%'\n )\n `).run()\n\n // Note: content_data table may not exist in all schemas\n try {\n await db.prepare(`\n DELETE FROM content_data\n WHERE content_id IN (\n SELECT id FROM content\n WHERE title LIKE 'Test %' OR title LIKE '%E2E%' OR title LIKE '%Playwright%' OR title LIKE '%Sample%'\n )\n `).run()\n } catch (e) {\n // Table doesn't exist, skip\n }\n\n // Step 2: Delete test content by pattern\n const contentResult = await db.prepare(`\n DELETE FROM content\n WHERE title LIKE 'Test %' OR title LIKE '%E2E%' OR title LIKE '%Playwright%' OR title LIKE '%Sample%'\n `).run()\n deletedCount += contentResult.meta?.changes || 0\n\n // Step 3: Delete child data for test users\n await db.prepare(`\n DELETE FROM api_tokens\n WHERE user_id IN (\n SELECT id FROM users\n WHERE email != 'admin@sonicjs.com' AND (email LIKE '%test%' OR email LIKE '%example.com%')\n )\n `).run()\n\n await db.prepare(`\n DELETE FROM media\n WHERE uploaded_by IN (\n SELECT id FROM users\n WHERE email != 'admin@sonicjs.com' AND (email LIKE '%test%' OR email LIKE '%example.com%')\n )\n `).run()\n\n // Step 4: Delete test users\n const usersResult = await db.prepare(`\n DELETE FROM users\n WHERE email != 'admin@sonicjs.com' AND (email LIKE '%test%' OR email LIKE '%example.com%')\n `).run()\n deletedCount += usersResult.meta?.changes || 0\n\n // Step 5: Delete child data for test collections\n try {\n await db.prepare(`\n DELETE FROM collection_fields\n WHERE collection_id IN (\n SELECT id FROM collections\n WHERE name LIKE 'test_%' OR name IN ('blog_posts', 'test_collection', 'products', 'articles')\n )\n `).run()\n } catch (e) {\n // Table doesn't exist\n }\n\n // Delete remaining content from test collections\n await db.prepare(`\n DELETE FROM content\n WHERE collection_id IN (\n SELECT id FROM collections\n WHERE name LIKE 'test_%' OR name IN ('blog_posts', 'test_collection', 'products', 'articles')\n )\n `).run()\n\n // Step 6: Delete test collections\n const collectionsResult = await db.prepare(`\n DELETE FROM collections\n WHERE name LIKE 'test_%' OR name IN ('blog_posts', 'test_collection', 'products', 'articles')\n `).run()\n deletedCount += collectionsResult.meta?.changes || 0\n\n // Step 7: Clean up orphaned data (skip if tables don't exist)\n try {\n await db.prepare(`\n DELETE FROM content_data WHERE content_id NOT IN (SELECT id FROM content)\n `).run()\n } catch (e) {\n // Table doesn't exist\n }\n\n try {\n await db.prepare(`\n DELETE FROM collection_fields WHERE collection_id NOT IN (SELECT id FROM collections)\n `).run()\n } catch (e) {\n // Table doesn't exist\n }\n\n try {\n await db.prepare(`\n DELETE FROM content_versions WHERE content_id NOT IN (SELECT id FROM content)\n `).run()\n } catch (e) {\n // Table doesn't exist\n }\n\n try {\n await db.prepare(`\n DELETE FROM workflow_history WHERE content_id NOT IN (SELECT id FROM content)\n `).run()\n } catch (e) {\n // Table doesn't exist\n }\n\n // Step 8: Delete old activity logs (keep only last 100)\n await db.prepare(`\n DELETE FROM activity_logs\n WHERE id NOT IN (\n SELECT id FROM activity_logs\n ORDER BY created_at DESC\n LIMIT 100\n )\n `).run()\n\n return c.json({\n success: true,\n deletedCount,\n message: 'Test data cleaned up successfully'\n })\n } catch (error) {\n console.error('Test cleanup error:', error)\n return c.json({\n success: false,\n error: error instanceof Error ? error.message : 'Unknown error'\n }, 500)\n }\n})\n\n/**\n * Clean up test users only\n * POST /test-cleanup/users\n */\napp.post('/test-cleanup/users', async (c: Context) => {\n const db = c.env.DB as D1Database\n\n // Only allow in development/test environments\n if (c.env.ENVIRONMENT === 'production') {\n return c.json({ error: 'Cleanup endpoint not available in production' }, 403)\n }\n\n try {\n // Delete test users (preserve admin)\n const result = await db.prepare(`\n DELETE FROM users\n WHERE email != 'admin@sonicjs.com'\n AND (\n email LIKE '%test%'\n OR email LIKE '%example.com%'\n OR first_name = 'Test'\n )\n `).run()\n\n return c.json({\n success: true,\n deletedCount: result.meta?.changes || 0,\n message: 'Test users cleaned up successfully'\n })\n } catch (error) {\n console.error('User cleanup error:', error)\n return c.json({\n success: false,\n error: error instanceof Error ? error.message : 'Unknown error'\n }, 500)\n }\n})\n\n/**\n * Clean up test collections only\n * POST /test-cleanup/collections\n */\napp.post('/test-cleanup/collections', async (c: Context) => {\n const db = c.env.DB as D1Database\n\n // Only allow in development/test environments\n if (c.env.ENVIRONMENT === 'production') {\n return c.json({ error: 'Cleanup endpoint not available in production' }, 403)\n }\n\n try {\n let deletedCount = 0\n\n // Get test collection IDs first\n const collections = await db.prepare(`\n SELECT id FROM collections\n WHERE name LIKE 'test_%'\n OR name IN ('blog_posts', 'test_collection', 'products', 'articles')\n `).all()\n\n if (collections.results && collections.results.length > 0) {\n const collectionIds = collections.results.map((c: any) => c.id)\n\n // Delete associated fields\n for (const id of collectionIds) {\n await db.prepare('DELETE FROM collection_fields WHERE collection_id = ?').bind(id).run()\n }\n\n // Delete associated content\n for (const id of collectionIds) {\n await db.prepare('DELETE FROM content WHERE collection_id = ?').bind(id).run()\n }\n\n // Delete the collections\n const result = await db.prepare(`\n DELETE FROM collections\n WHERE id IN (${collectionIds.map(() => '?').join(',')})\n `).bind(...collectionIds).run()\n\n deletedCount = result.meta?.changes || 0\n }\n\n return c.json({\n success: true,\n deletedCount,\n message: 'Test collections cleaned up successfully'\n })\n } catch (error) {\n console.error('Collection cleanup error:', error)\n return c.json({\n success: false,\n error: error instanceof Error ? error.message : 'Unknown error'\n }, 500)\n }\n})\n\n/**\n * Clean up test content only\n * POST /test-cleanup/content\n */\napp.post('/test-cleanup/content', async (c: Context) => {\n const db = c.env.DB as D1Database\n\n // Only allow in development/test environments\n if (c.env.ENVIRONMENT === 'production') {\n return c.json({ error: 'Cleanup endpoint not available in production' }, 403)\n }\n\n try {\n // Delete test content\n const result = await db.prepare(`\n DELETE FROM content\n WHERE title LIKE 'Test %'\n OR title LIKE '%E2E%'\n OR title LIKE '%Playwright%'\n OR title LIKE '%Sample%'\n `).run()\n\n // Clean up orphaned content_data\n await db.prepare(`\n DELETE FROM content_data\n WHERE content_id NOT IN (SELECT id FROM content)\n `).run()\n\n return c.json({\n success: true,\n deletedCount: result.meta?.changes || 0,\n message: 'Test content cleaned up successfully'\n })\n } catch (error) {\n console.error('Content cleanup error:', error)\n return c.json({\n success: false,\n error: error instanceof Error ? error.message : 'Unknown error'\n }, 500)\n }\n})\n\nexport default app\n","import { renderAdminLayoutCatalyst, AdminLayoutCatalystData } from '../layouts/admin-layout-catalyst.template'\nimport { renderAlert } from '../alert.template'\nimport { renderDynamicField, renderFieldGroup, FieldDefinition } from '../components/dynamic-field.template'\nimport { renderConfirmationDialog, getConfirmationDialogScript } from '../confirmation-dialog.template'\nimport { getTinyMCEScript, getTinyMCEInitScript } from '../../plugins/available/tinymce-plugin'\nimport { getQuillCDN, getQuillInitScript } from '../../plugins/core-plugins/quill-editor'\nimport { getMDXEditorScripts, getMDXEditorInitScript } from '../../plugins/available/easy-mdx'\n\nexport interface Collection {\n id: string\n name: string\n display_name: string\n description?: string\n schema: any\n}\n\nexport interface ContentFormData {\n id?: string\n title?: string\n slug?: string\n data?: any\n status?: string\n scheduled_publish_at?: number\n scheduled_unpublish_at?: number\n review_status?: string\n meta_title?: string\n meta_description?: string\n collection: Collection\n fields: FieldDefinition[]\n isEdit?: boolean\n error?: string\n success?: string\n validationErrors?: Record<string, string[]>\n workflowEnabled?: boolean // New flag to indicate if workflow plugin is active\n tinymceEnabled?: boolean // Flag to indicate if TinyMCE plugin is active\n tinymceSettings?: {\n apiKey?: string\n defaultHeight?: number\n defaultToolbar?: string\n skin?: string\n }\n quillEnabled?: boolean // Flag to indicate if Quill plugin is active\n quillSettings?: {\n version?: string\n defaultHeight?: number\n defaultToolbar?: string\n theme?: string\n }\n mdxeditorEnabled?: boolean // Flag to indicate if MDXEditor plugin is active\n mdxeditorSettings?: {\n defaultHeight?: number\n theme?: string\n toolbar?: string\n placeholder?: string\n }\n referrerParams?: string // URL parameters to preserve filters when returning to list\n user?: {\n name: string\n email: string\n role: string\n }\n version?: string\n}\n\nexport function renderContentFormPage(data: ContentFormData): string {\n const isEdit = data.isEdit || !!data.id\n const title = isEdit ? `Edit: ${data.title || 'Content'}` : `New ${data.collection.display_name}`\n\n // Construct back URL with preserved filters\n const backUrl = data.referrerParams\n ? `/admin/content?${data.referrerParams}`\n : `/admin/content?collection=${data.collection.id}`\n\n // Group fields by category\n const coreFields = data.fields.filter(f => ['title', 'slug', 'content'].includes(f.field_name))\n const contentFields = data.fields.filter(f => !['title', 'slug', 'content'].includes(f.field_name) && !f.field_name.startsWith('meta_'))\n const metaFields = data.fields.filter(f => f.field_name.startsWith('meta_'))\n \n // Helper function to get field value - title and slug are stored as columns, others in data JSON\n const getFieldValue = (fieldName: string) => {\n if (fieldName === 'title') return data.title || data.data?.[fieldName] || ''\n if (fieldName === 'slug') return data.slug || data.data?.[fieldName] || ''\n return data.data?.[fieldName] || ''\n }\n\n // Prepare plugin statuses for field rendering\n const pluginStatuses = {\n quillEnabled: data.quillEnabled || false,\n mdxeditorEnabled: data.mdxeditorEnabled || false,\n tinymceEnabled: data.tinymceEnabled || false\n }\n\n // Render field groups\n const coreFieldsHTML = coreFields\n .sort((a, b) => a.field_order - b.field_order)\n .map(field => renderDynamicField(field, {\n value: getFieldValue(field.field_name),\n errors: data.validationErrors?.[field.field_name] || [],\n pluginStatuses\n }))\n\n const contentFieldsHTML = contentFields\n .sort((a, b) => a.field_order - b.field_order)\n .map(field => renderDynamicField(field, {\n value: getFieldValue(field.field_name),\n errors: data.validationErrors?.[field.field_name] || [],\n pluginStatuses\n }))\n\n const metaFieldsHTML = metaFields\n .sort((a, b) => a.field_order - b.field_order)\n .map(field => renderDynamicField(field, {\n value: getFieldValue(field.field_name),\n errors: data.validationErrors?.[field.field_name] || [],\n pluginStatuses\n }))\n\n const pageContent = `\n <div class=\"space-y-6\">\n <!-- Header -->\n <div class=\"flex flex-col sm:flex-row sm:items-center sm:justify-between\">\n <div>\n <h1 class=\"text-2xl/8 font-semibold text-zinc-950 dark:text-white sm:text-xl/8\">${isEdit ? 'Edit Content' : 'New Content'}</h1>\n <p class=\"mt-2 text-sm/6 text-zinc-500 dark:text-zinc-400\">\n ${data.collection.description || `Manage ${data.collection.display_name.toLowerCase()} content`}\n </p>\n </div>\n <div class=\"mt-4 sm:mt-0 sm:ml-16 sm:flex-none\">\n <a href=\"${backUrl}\" class=\"inline-flex items-center justify-center rounded-lg bg-white dark:bg-zinc-800 px-3.5 py-2.5 text-sm font-semibold text-zinc-950 dark:text-white ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 hover:bg-zinc-50 dark:hover:bg-zinc-700 transition-colors shadow-sm\">\n <svg class=\"-ml-0.5 mr-1.5 h-5 w-5\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M10 19l-7-7m0 0l7-7m-7 7h18\"/>\n </svg>\n Back to Content\n </a>\n </div>\n </div>\n\n <!-- Form Container -->\n <div class=\"rounded-lg bg-white dark:bg-zinc-900 shadow-sm ring-1 ring-zinc-950/5 dark:ring-white/10 overflow-hidden\">\n <!-- Form Header -->\n <div class=\"border-b border-zinc-950/5 dark:border-white/10 px-6 py-6\">\n <div class=\"flex items-center gap-x-3\">\n <div class=\"flex h-12 w-12 items-center justify-center rounded-lg bg-zinc-50 dark:bg-zinc-800 ring-1 ring-zinc-950/10 dark:ring-white/10\">\n <svg class=\"h-6 w-6 text-zinc-950 dark:text-white\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\" stroke-width=\"1.5\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M19.5 14.25v-2.625a3.375 3.375 0 00-3.375-3.375h-1.5A1.125 1.125 0 0113.5 7.125v-1.5a3.375 3.375 0 00-3.375-3.375H8.25m0 12.75h7.5m-7.5 3H12M10.5 2.25H5.625c-.621 0-1.125.504-1.125 1.125v17.25c0 .621.504 1.125 1.125 1.125h12.75c.621 0 1.125-.504 1.125-1.125V11.25a9 9 0 00-9-9z\"/>\n </svg>\n </div>\n <div>\n <h2 class=\"text-base/7 font-semibold text-zinc-950 dark:text-white\">${data.collection.display_name}</h2>\n <p class=\"text-sm/6 text-zinc-500 dark:text-zinc-400\">${isEdit ? 'Update your content' : 'Create new content'}</p>\n </div>\n </div>\n </div>\n\n <!-- Form Content -->\n <div class=\"px-6 py-6\">\n <div id=\"form-messages\">\n ${data.error ? renderAlert({ type: 'error', message: data.error, dismissible: true }) : ''}\n ${data.success ? renderAlert({ type: 'success', message: data.success, dismissible: true }) : ''}\n </div>\n\n <div class=\"grid grid-cols-1 lg:grid-cols-3 gap-6\">\n <!-- Main Content Form -->\n <div class=\"lg:col-span-2\">\n <form\n id=\"content-form\"\n ${isEdit ? `hx-put=\"/admin/content/${data.id}\"` : `hx-post=\"/admin/content\"`}\n hx-target=\"#form-messages\"\n hx-encoding=\"multipart/form-data\"\n class=\"space-y-6\"\n >\n <input type=\"hidden\" name=\"collection_id\" value=\"${data.collection.id}\">\n ${isEdit ? `<input type=\"hidden\" name=\"id\" value=\"${data.id}\">` : ''}\n ${data.referrerParams ? `<input type=\"hidden\" name=\"referrer_params\" value=\"${data.referrerParams}\">` : ''}\n \n <!-- Core Fields -->\n ${renderFieldGroup('Basic Information', coreFieldsHTML)}\n \n <!-- Content Fields -->\n ${contentFields.length > 0 ? renderFieldGroup('Content Details', contentFieldsHTML) : ''}\n \n <!-- SEO & Meta Fields -->\n ${metaFields.length > 0 ? renderFieldGroup('SEO & Metadata', metaFieldsHTML, true) : ''}\n \n <div id=\"form-messages\"></div>\n </form>\n </div>\n\n <!-- Sidebar -->\n <div class=\"lg:col-span-1 space-y-6\">\n <!-- Publishing Options -->\n <div class=\"rounded-lg bg-zinc-50 dark:bg-zinc-800/50 shadow-sm ring-1 ring-zinc-950/5 dark:ring-white/10 p-6\">\n <h3 class=\"text-base/7 font-semibold text-zinc-950 dark:text-white mb-4\">Publishing</h3>\n\n ${data.workflowEnabled ? `\n <!-- Workflow Status (when workflow plugin is enabled) -->\n <div class=\"mb-4\">\n <label for=\"status\" class=\"block text-sm/6 font-medium text-zinc-950 dark:text-white\">Status</label>\n <div class=\"mt-2 grid grid-cols-1\">\n <select\n id=\"status\"\n name=\"status\"\n form=\"content-form\"\n class=\"col-start-1 row-start-1 w-full appearance-none rounded-md bg-white/5 dark:bg-white/5 py-1.5 pl-3 pr-8 text-base text-zinc-950 dark:text-white outline outline-1 -outline-offset-1 outline-zinc-500/30 dark:outline-zinc-400/30 *:bg-white dark:*:bg-zinc-800 focus-visible:outline focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-zinc-500 dark:focus-visible:outline-zinc-400 sm:text-sm/6\"\n >\n <option value=\"draft\" ${data.status === 'draft' ? 'selected' : ''}>Draft</option>\n <option value=\"review\" ${data.status === 'review' ? 'selected' : ''}>Under Review</option>\n <option value=\"published\" ${data.status === 'published' ? 'selected' : ''}>Published</option>\n <option value=\"archived\" ${data.status === 'archived' ? 'selected' : ''}>Archived</option>\n </select>\n <svg viewBox=\"0 0 16 16\" fill=\"currentColor\" data-slot=\"icon\" aria-hidden=\"true\" class=\"pointer-events-none col-start-1 row-start-1 mr-2 size-5 self-center justify-self-end text-zinc-600 dark:text-zinc-400 sm:size-4\">\n <path d=\"M4.22 6.22a.75.75 0 0 1 1.06 0L8 8.94l2.72-2.72a.75.75 0 1 1 1.06 1.06l-3.25 3.25a.75.75 0 0 1-1.06 0L4.22 7.28a.75.75 0 0 1 0-1.06Z\" clip-rule=\"evenodd\" fill-rule=\"evenodd\" />\n </svg>\n </div>\n </div>\n\n <!-- Scheduled Publishing -->\n <div class=\"mb-4\">\n <label class=\"block text-sm font-medium text-zinc-950 dark:text-white mb-2\">Schedule Publish</label>\n <input\n type=\"datetime-local\"\n name=\"scheduled_publish_at\"\n form=\"content-form\"\n value=\"${data.scheduled_publish_at ? new Date(data.scheduled_publish_at).toISOString().slice(0, 16) : ''}\"\n class=\"w-full rounded-lg bg-white dark:bg-zinc-800 px-3 py-2 text-sm text-zinc-950 dark:text-white shadow-sm ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 placeholder:text-zinc-400 dark:placeholder:text-zinc-500 focus:outline-none focus:ring-2 focus:ring-zinc-950 dark:focus:ring-white transition-shadow\"\n >\n <p class=\"text-xs text-zinc-500 dark:text-zinc-400 mt-1\">Leave empty to publish immediately</p>\n </div>\n\n <!-- Scheduled Unpublishing -->\n <div class=\"mb-6\">\n <label class=\"block text-sm font-medium text-zinc-950 dark:text-white mb-2\">Schedule Unpublish</label>\n <input\n type=\"datetime-local\"\n name=\"scheduled_unpublish_at\"\n form=\"content-form\"\n value=\"${data.scheduled_unpublish_at ? new Date(data.scheduled_unpublish_at).toISOString().slice(0, 16) : ''}\"\n class=\"w-full rounded-lg bg-white dark:bg-zinc-800 px-3 py-2 text-sm text-zinc-950 dark:text-white shadow-sm ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 placeholder:text-zinc-400 dark:placeholder:text-zinc-500 focus:outline-none focus:ring-2 focus:ring-zinc-950 dark:focus:ring-white transition-shadow\"\n >\n <p class=\"text-xs text-zinc-500 dark:text-zinc-400 mt-1\">Automatically unpublish at this time</p>\n </div>\n ` : `\n <!-- Simple Status (when workflow plugin is disabled) -->\n <div class=\"mb-6\">\n <label for=\"status\" class=\"block text-sm/6 font-medium text-zinc-950 dark:text-white\">Status</label>\n <div class=\"mt-2 grid grid-cols-1\">\n <select\n id=\"status\"\n name=\"status\"\n form=\"content-form\"\n class=\"col-start-1 row-start-1 w-full appearance-none rounded-md bg-white/5 dark:bg-white/5 py-1.5 pl-3 pr-8 text-base text-zinc-950 dark:text-white outline outline-1 -outline-offset-1 outline-zinc-500/30 dark:outline-zinc-400/30 *:bg-white dark:*:bg-zinc-800 focus-visible:outline focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-zinc-500 dark:focus-visible:outline-zinc-400 sm:text-sm/6\"\n >\n <option value=\"draft\" ${data.status === 'draft' ? 'selected' : ''}>Draft</option>\n <option value=\"published\" ${data.status === 'published' ? 'selected' : ''}>Published</option>\n </select>\n <svg viewBox=\"0 0 16 16\" fill=\"currentColor\" data-slot=\"icon\" aria-hidden=\"true\" class=\"pointer-events-none col-start-1 row-start-1 mr-2 size-5 self-center justify-self-end text-zinc-600 dark:text-zinc-400 sm:size-4\">\n <path d=\"M4.22 6.22a.75.75 0 0 1 1.06 0L8 8.94l2.72-2.72a.75.75 0 1 1 1.06 1.06l-3.25 3.25a.75.75 0 0 1-1.06 0L4.22 7.28a.75.75 0 0 1 0-1.06Z\" clip-rule=\"evenodd\" fill-rule=\"evenodd\" />\n </svg>\n </div>\n <p class=\"text-xs text-zinc-500 dark:text-zinc-400 mt-1\">Enable Workflow plugin for advanced status management</p>\n </div>\n `}\n </div>\n\n <!-- Content Info -->\n ${isEdit ? `\n <div class=\"rounded-lg bg-zinc-50 dark:bg-zinc-800/50 shadow-sm ring-1 ring-zinc-950/5 dark:ring-white/10 p-6\">\n <h3 class=\"text-base/7 font-semibold text-zinc-950 dark:text-white mb-4\">Content Info</h3>\n\n <dl class=\"space-y-3 text-sm\">\n <div>\n <dt class=\"text-zinc-500 dark:text-zinc-400\">Created</dt>\n <dd class=\"mt-1 text-zinc-950 dark:text-white\">${data.data?.created_at ? new Date(data.data.created_at).toLocaleDateString() : 'Unknown'}</dd>\n </div>\n <div>\n <dt class=\"text-zinc-500 dark:text-zinc-400\">Last Modified</dt>\n <dd class=\"mt-1 text-zinc-950 dark:text-white\">${data.data?.updated_at ? new Date(data.data.updated_at).toLocaleDateString() : 'Unknown'}</dd>\n </div>\n <div>\n <dt class=\"text-zinc-500 dark:text-zinc-400\">Author</dt>\n <dd class=\"mt-1 text-zinc-950 dark:text-white\">${data.data?.author || 'Unknown'}</dd>\n </div>\n ${data.data?.published_at ? `\n <div>\n <dt class=\"text-zinc-500 dark:text-zinc-400\">Published</dt>\n <dd class=\"mt-1 text-zinc-950 dark:text-white\">${new Date(data.data.published_at).toLocaleDateString()}</dd>\n </div>\n ` : ''}\n </dl>\n\n <div class=\"mt-4 pt-4 border-t border-zinc-950/5 dark:border-white/10\">\n <button\n type=\"button\"\n onclick=\"showVersionHistory('${data.id}')\"\n class=\"inline-flex items-center gap-x-1.5 text-sm font-medium text-zinc-950 dark:text-white hover:text-zinc-600 dark:hover:text-zinc-300 transition-colors\"\n >\n <svg class=\"h-4 w-4\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\" stroke-width=\"1.5\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M12 6v6h4.5m4.5 0a9 9 0 11-18 0 9 9 0 0118 0z\"/>\n </svg>\n View Version History\n </button>\n </div>\n </div>\n ` : ''}\n\n <!-- Quick Actions -->\n <div class=\"rounded-lg bg-zinc-50 dark:bg-zinc-800/50 shadow-sm ring-1 ring-zinc-950/5 dark:ring-white/10 p-6\">\n <h3 class=\"text-base/7 font-semibold text-zinc-950 dark:text-white mb-4\">Quick Actions</h3>\n\n <div class=\"space-y-2\">\n <button\n type=\"button\"\n onclick=\"previewContent()\"\n class=\"w-full inline-flex items-center gap-x-2 px-3 py-2 text-sm font-medium text-zinc-950 dark:text-white hover:bg-zinc-100 dark:hover:bg-zinc-700 rounded-lg transition-colors\"\n >\n <svg class=\"h-4 w-4\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\" stroke-width=\"1.5\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M15 12a3 3 0 11-6 0 3 3 0 016 0z\"></path>\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z\"></path>\n </svg>\n Preview Content\n </button>\n\n <button\n type=\"button\"\n onclick=\"duplicateContent()\"\n class=\"w-full inline-flex items-center gap-x-2 px-3 py-2 text-sm font-medium text-zinc-950 dark:text-white hover:bg-zinc-100 dark:hover:bg-zinc-700 rounded-lg transition-colors\"\n >\n <svg class=\"h-4 w-4\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\" stroke-width=\"1.5\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z\"></path>\n </svg>\n Duplicate Content\n </button>\n\n ${isEdit ? `\n <button\n type=\"button\"\n onclick=\"deleteContent('${data.id}')\"\n class=\"w-full inline-flex items-center gap-x-2 px-3 py-2 text-sm font-medium text-pink-700 dark:text-pink-300 hover:bg-pink-50 dark:hover:bg-pink-900/20 rounded-lg transition-colors\"\n >\n <svg class=\"h-4 w-4\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\" stroke-width=\"1.5\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M14.74 9l-.346 9m-4.788 0L9.26 9m9.968-3.21c.342.052.682.107 1.022.166m-1.022-.165L18.16 19.673a2.25 2.25 0 01-2.244 2.077H8.084a2.25 2.25 0 01-2.244-2.077L4.772 5.79m14.456 0a48.108 48.108 0 00-3.478-.397m-12 .562c.34-.059.68-.114 1.022-.165m0 0a48.11 48.11 0 013.478-.397m7.5 0v-.916c0-1.18-.91-2.164-2.09-2.201a51.964 51.964 0 00-3.32 0c-1.18.037-2.09 1.022-2.09 2.201v.916m7.5 0a48.667 48.667 0 00-7.5 0\"/>\n </svg>\n Delete Content\n </button>\n ` : ''}\n </div>\n </div>\n </div>\n\n <!-- Action Buttons -->\n <div class=\"mt-6 pt-6 border-t border-zinc-950/5 dark:border-white/10 flex items-center justify-between\">\n <a href=\"${backUrl}\" class=\"inline-flex items-center justify-center gap-x-1.5 rounded-lg bg-white dark:bg-zinc-800 px-3.5 py-2.5 text-sm font-semibold text-zinc-950 dark:text-white ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 hover:bg-zinc-50 dark:hover:bg-zinc-700 transition-colors shadow-sm\">\n <svg class=\"h-5 w-5\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\" stroke-width=\"1.5\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M6 18L18 6M6 6l12 12\"/>\n </svg>\n Cancel\n </a>\n\n <div class=\"flex items-center gap-x-3\">\n <button\n type=\"submit\"\n form=\"content-form\"\n name=\"action\"\n value=\"save\"\n class=\"inline-flex items-center justify-center gap-x-1.5 rounded-lg bg-zinc-950 dark:bg-white px-3.5 py-2.5 text-sm font-semibold text-white dark:text-zinc-950 hover:bg-zinc-800 dark:hover:bg-zinc-100 transition-colors shadow-sm\"\n >\n <svg class=\"h-5 w-5\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\" stroke-width=\"1.5\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M5 13l4 4L19 7\"/>\n </svg>\n ${isEdit ? 'Update' : 'Save'}\n </button>\n\n ${data.user?.role !== 'viewer' ? `\n <button\n type=\"submit\"\n form=\"content-form\"\n name=\"action\"\n value=\"save_and_publish\"\n class=\"inline-flex items-center justify-center gap-x-1.5 rounded-lg bg-lime-600 dark:bg-lime-500 px-3.5 py-2.5 text-sm font-semibold text-white hover:bg-lime-700 dark:hover:bg-lime-600 transition-colors shadow-sm\"\n >\n <svg class=\"h-5 w-5\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\" stroke-width=\"1.5\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 12.75L11.25 15 15 9.75M21 12a9 9 0 11-18 0 9 9 0 0118 0z\"/>\n </svg>\n ${isEdit ? 'Update' : 'Save'} & Publish\n </button>\n ` : ''}\n </div>\n </div>\n </div>\n </div>\n </div>\n\n <!-- Confirmation Dialogs -->\n ${renderConfirmationDialog({\n id: 'duplicate-content-confirm',\n title: 'Duplicate Content',\n message: 'Create a copy of this content?',\n confirmText: 'Duplicate',\n cancelText: 'Cancel',\n iconColor: 'blue',\n confirmClass: 'bg-blue-500 hover:bg-blue-400',\n onConfirm: 'performDuplicateContent()'\n })}\n\n ${renderConfirmationDialog({\n id: 'delete-content-confirm',\n title: 'Delete Content',\n message: 'Are you sure you want to delete this content? This action cannot be undone.',\n confirmText: 'Delete',\n cancelText: 'Cancel',\n iconColor: 'red',\n confirmClass: 'bg-red-500 hover:bg-red-400',\n onConfirm: `performDeleteContent('${data.id}')`\n })}\n\n ${getConfirmationDialogScript()}\n\n ${data.tinymceEnabled ? getTinyMCEScript(data.tinymceSettings?.apiKey) : '<!-- TinyMCE plugin not active -->'}\n\n ${data.quillEnabled ? getQuillCDN(data.quillSettings?.version) : '<!-- Quill plugin not active -->'}\n\n ${data.quillEnabled ? getQuillInitScript() : '<!-- Quill init script not needed -->'}\n\n ${data.mdxeditorEnabled ? getMDXEditorScripts() : '<!-- MDXEditor plugin not active -->'}\n\n <!-- Dynamic Field Scripts -->\n <script>\n // Field group toggle\n function toggleFieldGroup(groupId) {\n const content = document.getElementById(groupId + '-content');\n const icon = document.getElementById(groupId + '-icon');\n \n if (content.classList.contains('hidden')) {\n content.classList.remove('hidden');\n icon.classList.remove('rotate-[-90deg]');\n } else {\n content.classList.add('hidden');\n icon.classList.add('rotate-[-90deg]');\n }\n }\n\n // Media field functions\n let currentMediaFieldId = null;\n\n function openMediaSelector(fieldId) {\n currentMediaFieldId = fieldId;\n // Store the original value in case user cancels\n const originalValue = document.getElementById(fieldId)?.value || '';\n\n // Open media library modal\n const modal = document.createElement('div');\n modal.className = 'fixed inset-0 bg-black/50 backdrop-blur-sm flex items-center justify-center z-50';\n modal.id = 'media-selector-modal';\n modal.innerHTML = \\`\n <div class=\"rounded-xl bg-white dark:bg-zinc-900 shadow-xl ring-1 ring-zinc-950/5 dark:ring-white/10 p-6 w-full max-w-4xl max-h-[90vh] overflow-y-auto\">\n <h3 class=\"text-lg font-semibold text-zinc-950 dark:text-white mb-4\">Select Media</h3>\n <div id=\"media-grid-container\" hx-get=\"/admin/media/selector\" hx-trigger=\"load\"></div>\n <div class=\"mt-4 flex justify-end space-x-2\">\n <button\n onclick=\"cancelMediaSelection('\\${fieldId}', '\\${originalValue}')\"\n class=\"rounded-lg bg-white dark:bg-zinc-800 px-4 py-2 text-sm font-semibold text-zinc-950 dark:text-white ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 hover:bg-zinc-50 dark:hover:bg-zinc-700 transition-colors\">\n Cancel\n </button>\n <button\n onclick=\"closeMediaSelector()\"\n class=\"rounded-lg bg-zinc-950 dark:bg-white px-4 py-2 text-sm font-semibold text-white dark:text-zinc-950 hover:bg-zinc-800 dark:hover:bg-zinc-100 transition-colors\">\n OK\n </button>\n </div>\n </div>\n \\`;\n document.body.appendChild(modal);\n // Trigger HTMX for the modal content\n if (window.htmx) {\n htmx.process(modal);\n }\n }\n\n function closeMediaSelector() {\n const modal = document.getElementById('media-selector-modal');\n if (modal) {\n modal.remove();\n }\n currentMediaFieldId = null;\n }\n\n function cancelMediaSelection(fieldId, originalValue) {\n // Restore original value\n const hiddenInput = document.getElementById(fieldId);\n if (hiddenInput) {\n hiddenInput.value = originalValue;\n }\n\n // If original value was empty, hide the preview and show select button\n if (!originalValue) {\n const preview = document.getElementById(fieldId + '-preview');\n if (preview) {\n preview.classList.add('hidden');\n }\n }\n\n // Close modal\n closeMediaSelector();\n }\n\n function clearMediaField(fieldId) {\n document.getElementById(fieldId).value = '';\n document.getElementById(fieldId + '-preview').classList.add('hidden');\n }\n\n // Global function called by media selector buttons\n window.selectMediaFile = function(mediaId, mediaUrl, filename) {\n if (!currentMediaFieldId) {\n console.error('No field ID set for media selection');\n return;\n }\n\n const fieldId = currentMediaFieldId;\n\n // Set the hidden input value to the media URL (not ID)\n const hiddenInput = document.getElementById(fieldId);\n if (hiddenInput) {\n hiddenInput.value = mediaUrl;\n }\n\n // Update the preview\n const preview = document.getElementById(fieldId + '-preview');\n if (preview) {\n preview.innerHTML = \\`<img src=\"\\${mediaUrl}\" alt=\"\\${filename}\" class=\"w-32 h-32 object-cover rounded-lg border border-white/20\">\\`;\n preview.classList.remove('hidden');\n }\n\n // Show the remove button by finding the media actions container and updating it\n const mediaField = hiddenInput?.closest('.media-field-container');\n if (mediaField) {\n const actionsDiv = mediaField.querySelector('.media-actions');\n if (actionsDiv && !actionsDiv.querySelector('button:has-text(\"Remove\")')) {\n const removeBtn = document.createElement('button');\n removeBtn.type = 'button';\n removeBtn.onclick = () => clearMediaField(fieldId);\n removeBtn.className = 'inline-flex items-center px-4 py-2 bg-red-600 text-white rounded-xl hover:bg-red-700 transition-all';\n removeBtn.textContent = 'Remove';\n actionsDiv.appendChild(removeBtn);\n }\n }\n\n // DON'T close the modal - let user click OK button\n // Visual feedback: highlight the selected item\n document.querySelectorAll('#media-selector-grid [data-media-id]').forEach(el => {\n el.classList.remove('ring-2', 'ring-lime-500', 'dark:ring-lime-400');\n });\n const selectedItem = document.querySelector(\\`#media-selector-grid [data-media-id=\"\\${mediaId}\"]\\`);\n if (selectedItem) {\n selectedItem.classList.add('ring-2', 'ring-lime-500', 'dark:ring-lime-400');\n }\n };\n\n function setMediaField(fieldId, mediaUrl) {\n document.getElementById(fieldId).value = mediaUrl;\n const preview = document.getElementById(fieldId + '-preview');\n preview.innerHTML = \\`<img src=\"\\${mediaUrl}\" alt=\"Selected media\" class=\"w-32 h-32 object-cover rounded-lg ring-1 ring-zinc-950/10 dark:ring-white/10\">\\`;\n preview.classList.remove('hidden');\n\n // Close modal\n document.querySelector('.fixed.inset-0')?.remove();\n }\n\n // Custom select options\n function addCustomOption(input, selectId) {\n const value = input.value.trim();\n if (value) {\n const select = document.getElementById(selectId);\n const option = document.createElement('option');\n option.value = value;\n option.text = value;\n option.selected = true;\n select.appendChild(option);\n input.value = '';\n }\n }\n\n // Quick actions\n function previewContent() {\n const form = document.getElementById('content-form');\n const formData = new FormData(form);\n \n // Open preview in new window\n const preview = window.open('', '_blank');\n preview.document.write('<p>Loading preview...</p>');\n \n fetch('/admin/content/preview', {\n method: 'POST',\n body: formData\n })\n .then(response => response.text())\n .then(html => {\n preview.document.open();\n preview.document.write(html);\n preview.document.close();\n })\n .catch(error => {\n preview.document.write('<p>Error loading preview</p>');\n });\n }\n\n function duplicateContent() {\n showConfirmDialog('duplicate-content-confirm');\n }\n\n function performDuplicateContent() {\n const form = document.getElementById('content-form');\n const formData = new FormData(form);\n formData.append('action', 'duplicate');\n\n fetch('/admin/content/duplicate', {\n method: 'POST',\n body: formData\n })\n .then(response => response.json())\n .then(data => {\n if (data.success) {\n window.location.href = \\`/admin/content/\\${data.id}/edit\\`;\n } else {\n alert('Error duplicating content');\n }\n });\n }\n\n function deleteContent(contentId) {\n showConfirmDialog('delete-content-confirm');\n }\n\n function performDeleteContent(contentId) {\n fetch(\\`/admin/content/\\${contentId}\\`, {\n method: 'DELETE'\n })\n .then(response => {\n if (response.ok) {\n window.location.href = '/admin/content';\n } else {\n alert('Error deleting content');\n }\n });\n }\n\n function showVersionHistory(contentId) {\n // Create and show version history modal\n const modal = document.createElement('div');\n modal.className = 'fixed inset-0 bg-black/50 backdrop-blur-sm flex items-center justify-center z-50';\n modal.innerHTML = \\`\n <div id=\"version-history-content\">\n <div class=\"flex items-center justify-center h-32\">\n <div class=\"animate-spin rounded-full h-8 w-8 border-b-2 border-blue-600 dark:border-blue-400\"></div>\n </div>\n </div>\n \\`;\n document.body.appendChild(modal);\n\n // Load version history\n fetch(\\`/admin/content/\\${contentId}/versions\\`)\n .then(response => response.text())\n .then(html => {\n document.getElementById('version-history-content').innerHTML = html;\n })\n .catch(error => {\n console.error('Error loading version history:', error);\n document.getElementById('version-history-content').innerHTML = '<p class=\"text-zinc-950 dark:text-white\">Error loading version history</p>';\n });\n }\n\n // Auto-save functionality\n let autoSaveTimeout;\n function scheduleAutoSave() {\n clearTimeout(autoSaveTimeout);\n autoSaveTimeout = setTimeout(() => {\n const form = document.getElementById('content-form');\n const formData = new FormData(form);\n formData.append('action', 'autosave');\n \n fetch(form.action, {\n method: 'POST',\n body: formData\n })\n .then(response => {\n if (response.ok) {\n console.log('Auto-saved');\n }\n })\n .catch(error => console.error('Auto-save failed:', error));\n }, 30000); // Auto-save every 30 seconds\n }\n\n // Bind auto-save to form changes\n document.addEventListener('DOMContentLoaded', function() {\n const form = document.getElementById('content-form');\n form.addEventListener('input', scheduleAutoSave);\n form.addEventListener('change', scheduleAutoSave);\n });\n\n ${data.tinymceEnabled ? getTinyMCEInitScript({\n skin: data.tinymceSettings?.skin,\n defaultHeight: data.tinymceSettings?.defaultHeight,\n defaultToolbar: data.tinymceSettings?.defaultToolbar\n }) : ''}\n\n ${data.mdxeditorEnabled ? getMDXEditorInitScript({\n defaultHeight: data.mdxeditorSettings?.defaultHeight,\n toolbar: data.mdxeditorSettings?.toolbar,\n placeholder: data.mdxeditorSettings?.placeholder\n }) : ''}\n </script>\n `\n\n const layoutData: AdminLayoutCatalystData = {\n title: title,\n pageTitle: 'Content Management',\n currentPath: '/admin/content',\n user: data.user,\n content: pageContent,\n version: data.version\n }\n\n return renderAdminLayoutCatalyst(layoutData)\n}\n","export interface FieldDefinition {\n id: string\n field_name: string\n field_type: string\n field_label: string\n field_options: any // JSON options\n field_order: number\n is_required: boolean\n is_searchable: boolean\n}\n\nexport interface FieldRenderOptions {\n value?: any\n errors?: string[]\n disabled?: boolean\n className?: string\n pluginStatuses?: {\n quillEnabled?: boolean\n mdxeditorEnabled?: boolean\n tinymceEnabled?: boolean\n }\n}\n\nexport function renderDynamicField(field: FieldDefinition, options: FieldRenderOptions = {}): string {\n const { value = '', errors = [], disabled = false, className = '', pluginStatuses = {} } = options\n const opts = field.field_options || {}\n const required = field.is_required ? 'required' : ''\n const baseClasses = `w-full rounded-lg px-3 py-2 text-sm text-zinc-950 dark:text-white bg-white dark:bg-zinc-800 shadow-sm ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 placeholder:text-zinc-400 dark:placeholder:text-zinc-500 focus:outline-none focus:ring-2 focus:ring-zinc-950 dark:focus:ring-white transition-shadow ${className}`\n const errorClasses = errors.length > 0 ? 'ring-pink-600 dark:ring-pink-500 focus:ring-pink-600 dark:focus:ring-pink-500' : ''\n\n const fieldId = `field-${field.field_name}`\n const fieldName = field.field_name\n\n // Check if this is a plugin-based field type and if the plugin is inactive\n // If so, fall back to textarea with a warning\n let fallbackToTextarea = false\n let fallbackWarning = ''\n\n if (field.field_type === 'quill' && !pluginStatuses.quillEnabled) {\n fallbackToTextarea = true\n fallbackWarning = '⚠️ Quill Editor plugin is inactive. Using textarea fallback.'\n } else if (field.field_type === 'mdxeditor' && !pluginStatuses.mdxeditorEnabled) {\n fallbackToTextarea = true\n fallbackWarning = '⚠️ MDXEditor plugin is inactive. Using textarea fallback.'\n } else if (field.field_type === 'tinymce' && !pluginStatuses.tinymceEnabled) {\n fallbackToTextarea = true\n fallbackWarning = '⚠️ TinyMCE plugin is inactive. Using textarea fallback.'\n }\n\n // If falling back to textarea, render it with a warning\n if (fallbackToTextarea) {\n return `\n <div>\n ${fallbackWarning ? `<div class=\"mb-2 px-3 py-2 bg-amber-50 dark:bg-amber-900/20 text-amber-900 dark:text-amber-200 text-xs rounded-lg border border-amber-200 dark:border-amber-800\">${fallbackWarning}</div>` : ''}\n <textarea\n id=\"${fieldId}\"\n name=\"${fieldName}\"\n rows=\"${opts.rows || opts.height ? Math.floor(opts.height / 25) : 10}\"\n placeholder=\"${opts.placeholder || ''}\"\n maxlength=\"${opts.maxLength || ''}\"\n class=\"${baseClasses} ${errorClasses} resize-y\"\n ${required}\n ${disabled ? 'disabled' : ''}\n >${escapeHtml(value)}</textarea>\n </div>\n `\n }\n\n let fieldHTML = ''\n\n switch (field.field_type) {\n case 'text':\n let patternHelp = ''\n let autoSlugScript = ''\n \n if (opts.pattern) {\n if (opts.pattern === '^[a-z0-9-]+$' || opts.pattern === '^[a-zA-Z0-9_-]+$') {\n patternHelp = '<p class=\"mt-2 text-xs text-zinc-500 dark:text-zinc-400\">Use letters, numbers, underscores, and hyphens only</p>'\n\n // Add auto-slug generation for slug fields\n if (fieldName === 'slug') {\n patternHelp += '<button type=\"button\" class=\"mt-1 text-xs text-cyan-600 dark:text-cyan-400 hover:text-cyan-700 dark:hover:text-cyan-300\" onclick=\"generateSlugFromTitle(\\'${fieldId}\\')\">Generate from title</button>'\n autoSlugScript = `\n <script>\n function generateSlugFromTitle(slugFieldId) {\n const titleField = document.querySelector('input[name=\"title\"]');\n const slugField = document.getElementById(slugFieldId);\n if (titleField && slugField) {\n const slug = titleField.value\n .toLowerCase()\n .replace(/[^a-z0-9\\\\s_-]/g, '')\n .replace(/\\\\s+/g, '-')\n .replace(/[-_]+/g, '-')\n .replace(/^[-_]|[-_]$/g, '');\n slugField.value = slug;\n }\n }\n \n // Auto-generate slug when title changes\n document.addEventListener('DOMContentLoaded', function() {\n const titleField = document.querySelector('input[name=\"title\"]');\n const slugField = document.getElementById('${fieldId}');\n if (titleField && slugField && !slugField.value) {\n titleField.addEventListener('input', function() {\n if (!slugField.value) {\n generateSlugFromTitle('${fieldId}');\n }\n });\n }\n });\n </script>\n `\n }\n } else {\n patternHelp = '<p class=\"mt-2 text-xs text-zinc-500 dark:text-zinc-400\">Must match required format</p>'\n }\n }\n \n fieldHTML = `\n <input \n type=\"text\" \n id=\"${fieldId}\"\n name=\"${fieldName}\"\n value=\"${escapeHtml(value)}\"\n placeholder=\"${opts.placeholder || ''}\"\n maxlength=\"${opts.maxLength || ''}\"\n ${opts.pattern ? `data-pattern=\"${opts.pattern}\"` : ''}\n class=\"${baseClasses} ${errorClasses}\"\n ${required}\n ${disabled ? 'disabled' : ''}\n >\n ${patternHelp}\n ${autoSlugScript}\n ${opts.pattern ? `\n <script>\n (function() {\n const field = document.getElementById('${fieldId}');\n const pattern = new RegExp('${opts.pattern}');\n \n field.addEventListener('input', function() {\n if (this.value && !pattern.test(this.value)) {\n if ('${opts.pattern}' === '^[a-zA-Z0-9_-]+$' || '${opts.pattern}' === '^[a-z0-9-]+$') {\n this.setCustomValidity('Please use only letters, numbers, underscores, and hyphens.');\n } else {\n this.setCustomValidity('Please enter a valid format.');\n }\n } else {\n this.setCustomValidity('');\n }\n });\n \n field.addEventListener('blur', function() {\n this.reportValidity();\n });\n })();\n </script>\n ` : ''}\n `\n break\n\n case 'textarea':\n fieldHTML = `\n <textarea\n id=\"${fieldId}\"\n name=\"${fieldName}\"\n rows=\"${opts.rows || 6}\"\n placeholder=\"${opts.placeholder || ''}\"\n maxlength=\"${opts.maxLength || ''}\"\n class=\"${baseClasses} ${errorClasses} resize-y\"\n ${required}\n ${disabled ? 'disabled' : ''}\n >${escapeHtml(value)}</textarea>\n `\n break\n\n case 'richtext':\n fieldHTML = `\n <div class=\"richtext-container\" data-height=\"${opts.height || 300}\" data-toolbar=\"${opts.toolbar || 'full'}\">\n <textarea\n id=\"${fieldId}\"\n name=\"${fieldName}\"\n class=\"${baseClasses} ${errorClasses} min-h-[${opts.height || 300}px]\"\n ${required}\n ${disabled ? 'disabled' : ''}\n >${escapeHtml(value)}</textarea>\n </div>\n `\n break\n\n case 'quill':\n // Quill WYSIWYG Editor\n fieldHTML = `\n <div class=\"quill-editor-container\" data-field-id=\"${fieldId}\">\n <!-- Quill Editor Container -->\n <div\n id=\"${fieldId}-editor\"\n class=\"quill-editor bg-white dark:bg-zinc-900 text-zinc-900 dark:text-zinc-100\"\n data-theme=\"${opts.theme || 'snow'}\"\n data-toolbar=\"${opts.toolbar || 'full'}\"\n data-placeholder=\"${opts.placeholder || 'Enter content...'}\"\n data-height=\"${opts.height || 300}\"\n >${value}</div>\n\n <!-- Hidden input to store the actual content for form submission -->\n <input\n type=\"hidden\"\n id=\"${fieldId}\"\n name=\"${fieldName}\"\n value=\"${escapeHtml(value)}\"\n >\n </div>\n `\n break\n\n case 'mdxeditor':\n // MDXEditor Rich Text Editor - renders same container as richtext\n // The MDXEditor plugin initialization script will handle the editor initialization\n fieldHTML = `\n <div class=\"richtext-container\" data-height=\"${opts.height || 300}\" data-toolbar=\"${opts.toolbar || 'full'}\">\n <textarea\n id=\"${fieldId}\"\n name=\"${fieldName}\"\n class=\"${baseClasses} ${errorClasses} min-h-[${opts.height || 300}px]\"\n ${required}\n ${disabled ? 'disabled' : ''}\n >${escapeHtml(value)}</textarea>\n </div>\n `\n break\n\n case 'number':\n fieldHTML = `\n <input \n type=\"number\" \n id=\"${fieldId}\"\n name=\"${fieldName}\"\n value=\"${value}\"\n min=\"${opts.min || ''}\"\n max=\"${opts.max || ''}\"\n step=\"${opts.step || ''}\"\n placeholder=\"${opts.placeholder || ''}\"\n class=\"${baseClasses} ${errorClasses}\"\n ${required}\n ${disabled ? 'disabled' : ''}\n >\n `\n break\n \n case 'boolean':\n const checked = value === true || value === 'true' || value === '1' ? 'checked' : ''\n fieldHTML = `\n <div class=\"flex items-center space-x-3\">\n <input \n type=\"checkbox\" \n id=\"${fieldId}\"\n name=\"${fieldName}\"\n value=\"true\"\n class=\"w-5 h-5 text-blue-600 bg-white/10 border-white/20 rounded focus:ring-blue-500 focus:ring-2\"\n ${checked}\n ${disabled ? 'disabled' : ''}\n >\n <label for=\"${fieldId}\" class=\"text-sm text-gray-300\">\n ${opts.checkboxLabel || field.field_label}\n </label>\n </div>\n <input type=\"hidden\" name=\"${fieldName}_submitted\" value=\"1\">\n `\n break\n \n case 'date':\n fieldHTML = `\n <input\n type=\"date\"\n id=\"${fieldId}\"\n name=\"${fieldName}\"\n value=\"${value}\"\n min=\"${opts.min || ''}\"\n max=\"${opts.max || ''}\"\n class=\"${baseClasses} ${errorClasses}\"\n ${required}\n ${disabled ? 'disabled' : ''}\n >\n `\n break\n\n case 'datetime':\n fieldHTML = `\n <input\n type=\"datetime-local\"\n id=\"${fieldId}\"\n name=\"${fieldName}\"\n value=\"${value}\"\n min=\"${opts.min || ''}\"\n max=\"${opts.max || ''}\"\n class=\"${baseClasses} ${errorClasses}\"\n ${required}\n ${disabled ? 'disabled' : ''}\n >\n `\n break\n\n case 'slug':\n // Slug fields behave like text fields but with special validation\n let slugPattern = opts.pattern || '^[a-z0-9-]+$'\n let slugHelp = '<p class=\"mt-2 text-xs text-zinc-500 dark:text-zinc-400\">Use lowercase letters, numbers, and hyphens only</p>'\n slugHelp += '<button type=\"button\" class=\"mt-1 text-xs text-cyan-600 dark:text-cyan-400 hover:text-cyan-700 dark:hover:text-cyan-300\" onclick=\"generateSlugFromTitle(\\'${fieldId}\\')\">Generate from title</button>'\n\n fieldHTML = `\n <input\n type=\"text\"\n id=\"${fieldId}\"\n name=\"${fieldName}\"\n value=\"${escapeHtml(value)}\"\n placeholder=\"${opts.placeholder || 'url-friendly-slug'}\"\n maxlength=\"${opts.maxLength || ''}\"\n data-pattern=\"${slugPattern}\"\n class=\"${baseClasses} ${errorClasses}\"\n ${required}\n ${disabled ? 'disabled' : ''}\n >\n ${slugHelp}\n <script>\n (function() {\n const field = document.getElementById('${fieldId}');\n const pattern = new RegExp('${slugPattern}');\n\n field.addEventListener('input', function() {\n if (this.value && !pattern.test(this.value)) {\n this.setCustomValidity('Please use only lowercase letters, numbers, and hyphens.');\n } else {\n this.setCustomValidity('');\n }\n });\n\n field.addEventListener('blur', function() {\n this.reportValidity();\n });\n })();\n\n function generateSlugFromTitle(slugFieldId) {\n const titleField = document.querySelector('input[name=\"title\"]');\n const slugField = document.getElementById(slugFieldId);\n if (titleField && slugField) {\n const slug = titleField.value\n .toLowerCase()\n .replace(/[^a-z0-9\\\\s_-]/g, '')\n .replace(/\\\\s+/g, '-')\n .replace(/[-_]+/g, '-')\n .replace(/^[-_]|[-_]$/g, '');\n slugField.value = slug;\n }\n }\n\n // Auto-generate slug when title changes\n document.addEventListener('DOMContentLoaded', function() {\n const titleField = document.querySelector('input[name=\"title\"]');\n const slugField = document.getElementById('${fieldId}');\n if (titleField && slugField && !slugField.value) {\n titleField.addEventListener('input', function() {\n if (!slugField.value) {\n generateSlugFromTitle('${fieldId}');\n }\n });\n }\n });\n </script>\n `\n break\n\n case 'select':\n const options = opts.options || []\n const multiple = opts.multiple ? 'multiple' : ''\n const selectedValues = Array.isArray(value) ? value : [value]\n \n fieldHTML = `\n <select \n id=\"${fieldId}\"\n name=\"${fieldName}${opts.multiple ? '[]' : ''}\"\n class=\"${baseClasses} ${errorClasses}\"\n ${multiple}\n ${required}\n ${disabled ? 'disabled' : ''}\n >\n ${!required && !opts.multiple ? '<option value=\"\">Choose an option...</option>' : ''}\n ${options.map((option: any) => {\n const optionValue = typeof option === 'string' ? option : option.value\n const optionLabel = typeof option === 'string' ? option : option.label\n const selected = selectedValues.includes(optionValue) ? 'selected' : ''\n return `<option value=\"${escapeHtml(optionValue)}\" ${selected}>${escapeHtml(optionLabel)}</option>`\n }).join('')}\n </select>\n ${opts.allowCustom ? `\n <div class=\"mt-2\">\n <input \n type=\"text\" \n placeholder=\"Add custom option...\"\n class=\"${baseClasses.replace('border-white/10', 'border-white/5')} text-sm\"\n onkeypress=\"if(event.key==='Enter'){addCustomOption(this, '${fieldId}');event.preventDefault();}\"\n >\n </div>\n ` : ''}\n `\n break\n \n case 'media':\n fieldHTML = `\n <div class=\"media-field-container\">\n <input type=\"hidden\" id=\"${fieldId}\" name=\"${fieldName}\" value=\"${value}\">\n <div class=\"media-preview ${value ? '' : 'hidden'}\" id=\"${fieldId}-preview\">\n ${value ? `<img src=\"${value}\" alt=\"Selected media\" class=\"w-32 h-32 object-cover rounded-lg border border-white/20\">` : ''}\n </div>\n <div class=\"media-actions mt-2 space-x-2\">\n <button\n type=\"button\"\n onclick=\"openMediaSelector('${fieldId}')\"\n class=\"inline-flex items-center px-4 py-2 bg-blue-600 text-white rounded-xl hover:bg-blue-700 transition-all\"\n ${disabled ? 'disabled' : ''}\n >\n <svg class=\"w-4 h-4 mr-2\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z\"></path>\n </svg>\n Select Media\n </button>\n ${value ? `\n <button\n type=\"button\"\n onclick=\"clearMediaField('${fieldId}')\"\n class=\"inline-flex items-center px-4 py-2 bg-red-600 text-white rounded-xl hover:bg-red-700 transition-all\"\n ${disabled ? 'disabled' : ''}\n >\n Remove\n </button>\n ` : ''}\n </div>\n </div>\n `\n break\n\n default:\n fieldHTML = `\n <input \n type=\"text\" \n id=\"${fieldId}\"\n name=\"${fieldName}\"\n value=\"${escapeHtml(value)}\"\n class=\"${baseClasses} ${errorClasses}\"\n ${required}\n ${disabled ? 'disabled' : ''}\n >\n `\n }\n \n return `\n <div class=\"form-group\">\n <label for=\"${fieldId}\" class=\"block text-sm/6 font-medium text-zinc-950 dark:text-white mb-2\">\n ${escapeHtml(field.field_label)}\n ${field.is_required ? '<span class=\"text-pink-600 dark:text-pink-400 ml-1\">*</span>' : ''}\n </label>\n ${fieldHTML}\n ${errors.length > 0 ? `\n <div class=\"mt-2 text-sm text-pink-600 dark:text-pink-400\">\n ${errors.map(error => `<div>${escapeHtml(error)}</div>`).join('')}\n </div>\n ` : ''}\n ${opts.helpText ? `\n <div class=\"mt-2 text-xs text-zinc-500 dark:text-zinc-400\">\n ${escapeHtml(opts.helpText)}\n </div>\n ` : ''}\n </div>\n `\n}\n\nexport function renderFieldGroup(title: string, fields: string[], collapsible: boolean = false): string {\n const groupId = title.toLowerCase().replace(/\\s+/g, '-')\n\n return `\n <div class=\"field-group rounded-lg bg-white dark:bg-zinc-900 shadow-sm ring-1 ring-zinc-950/5 dark:ring-white/10 mb-6\">\n <div class=\"field-group-header border-b border-zinc-950/5 dark:border-white/10 px-6 py-4 ${collapsible ? 'cursor-pointer' : ''}\" ${collapsible ? `onclick=\"toggleFieldGroup('${groupId}')\"` : ''}>\n <h3 class=\"text-base/7 font-semibold text-zinc-950 dark:text-white flex items-center\">\n ${escapeHtml(title)}\n ${collapsible ? `\n <svg id=\"${groupId}-icon\" class=\"w-5 h-5 ml-2 transform transition-transform text-zinc-500 dark:text-zinc-400\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M19 9l-7 7-7-7\"></path>\n </svg>\n ` : ''}\n </h3>\n </div>\n <div id=\"${groupId}-content\" class=\"field-group-content px-6 py-6 space-y-6 ${collapsible ? 'collapsible' : ''}\">\n ${fields.join('')}\n </div>\n </div>\n `\n}\n\nfunction escapeHtml(text: string): string {\n if (typeof text !== 'string') return String(text || '')\n return text.replace(/[&<>\"']/g, (char) => ({\n '&': '&',\n '<': '<',\n '>': '>',\n '\"': '"',\n \"'\": '''\n }[char] || char))\n}","/**\n * Plugin Builder SDK\n * \n * Provides a fluent API for building SonicJS plugins\n */\n\nimport { Hono } from 'hono'\nimport { z } from 'zod'\nimport { Plugin, PluginBuilderOptions, PluginRoutes, PluginMiddleware, PluginModel, PluginService, PluginAdminPage, PluginComponent, PluginHook, PluginMenuItem } from '../types'\n\nexport class PluginBuilder {\n private plugin: Partial<Plugin>\n\n constructor(options: PluginBuilderOptions) {\n this.plugin = {\n name: options.name,\n version: options.version,\n description: options.description,\n author: options.author,\n dependencies: options.dependencies,\n routes: [],\n middleware: [],\n models: [],\n services: [],\n adminPages: [],\n adminComponents: [],\n menuItems: [],\n hooks: []\n }\n }\n\n /**\n * Create a new plugin builder\n */\n static create(options: PluginBuilderOptions): PluginBuilder {\n return new PluginBuilder(options)\n }\n\n /**\n * Add metadata to the plugin\n */\n metadata(metadata: {\n description?: string\n author?: Plugin['author']\n license?: string\n compatibility?: string\n dependencies?: string[]\n }): PluginBuilder {\n Object.assign(this.plugin, metadata)\n return this\n }\n\n /**\n * Add routes to plugin\n */\n addRoutes(routes: PluginRoutes[]): PluginBuilder {\n this.plugin.routes = [...(this.plugin.routes || []), ...routes]\n return this\n }\n\n /**\n * Add a single route to plugin\n */\n addRoute(path: string, handler: Hono, options?: {\n description?: string\n requiresAuth?: boolean\n roles?: string[]\n priority?: number\n }): PluginBuilder {\n const route: PluginRoutes = {\n path,\n handler,\n ...options\n }\n this.plugin.routes = [...(this.plugin.routes || []), route]\n return this\n }\n\n /**\n * Add middleware to plugin\n */\n addMiddleware(middleware: PluginMiddleware[]): PluginBuilder {\n this.plugin.middleware = [...(this.plugin.middleware || []), ...middleware]\n return this\n }\n\n /**\n * Add a single middleware to plugin\n */\n addSingleMiddleware(name: string, handler: any, options?: {\n description?: string\n priority?: number\n routes?: string[]\n global?: boolean\n }): PluginBuilder {\n const middleware: PluginMiddleware = {\n name,\n handler,\n ...options\n }\n this.plugin.middleware = [...(this.plugin.middleware || []), middleware]\n return this\n }\n\n /**\n * Add models to plugin\n */\n addModels(models: PluginModel[]): PluginBuilder {\n this.plugin.models = [...(this.plugin.models || []), ...models]\n return this\n }\n\n /**\n * Add a single model to plugin\n */\n addModel(name: string, options: {\n tableName: string\n schema: z.ZodSchema\n migrations: string[]\n relationships?: PluginModel['relationships']\n extendsContent?: boolean\n }): PluginBuilder {\n const model: PluginModel = {\n name,\n ...options\n }\n this.plugin.models = [...(this.plugin.models || []), model]\n return this\n }\n\n /**\n * Add services to plugin\n */\n addServices(services: PluginService[]): PluginBuilder {\n this.plugin.services = [...(this.plugin.services || []), ...services]\n return this\n }\n\n /**\n * Add a single service to plugin\n */\n addService(name: string, implementation: any, options?: {\n description?: string\n dependencies?: string[]\n singleton?: boolean\n }): PluginBuilder {\n const service: PluginService = {\n name,\n implementation,\n ...options\n }\n this.plugin.services = [...(this.plugin.services || []), service]\n return this\n }\n\n /**\n * Add admin pages to plugin\n */\n addAdminPages(pages: PluginAdminPage[]): PluginBuilder {\n this.plugin.adminPages = [...(this.plugin.adminPages || []), ...pages]\n return this\n }\n\n /**\n * Add a single admin page to plugin\n */\n addAdminPage(path: string, title: string, component: string, options?: {\n description?: string\n permissions?: string[]\n icon?: string\n menuItem?: PluginMenuItem\n }): PluginBuilder {\n const page: PluginAdminPage = {\n path,\n title,\n component,\n ...options\n }\n this.plugin.adminPages = [...(this.plugin.adminPages || []), page]\n return this\n }\n\n /**\n * Add admin components to plugin\n */\n addComponents(components: PluginComponent[]): PluginBuilder {\n this.plugin.adminComponents = [...(this.plugin.adminComponents || []), ...components]\n return this\n }\n\n /**\n * Add a single admin component to plugin\n */\n addComponent(name: string, template: (props: any) => string, options?: {\n description?: string\n propsSchema?: z.ZodSchema\n }): PluginBuilder {\n const component: PluginComponent = {\n name,\n template,\n ...options\n }\n this.plugin.adminComponents = [...(this.plugin.adminComponents || []), component]\n return this\n }\n\n /**\n * Add menu items to plugin\n */\n addMenuItems(items: PluginMenuItem[]): PluginBuilder {\n this.plugin.menuItems = [...(this.plugin.menuItems || []), ...items]\n return this\n }\n\n /**\n * Add a single menu item to plugin\n */\n addMenuItem(label: string, path: string, options?: {\n icon?: string\n order?: number\n parent?: string\n permissions?: string[]\n }): PluginBuilder {\n const menuItem: PluginMenuItem = {\n label,\n path,\n ...options\n }\n this.plugin.menuItems = [...(this.plugin.menuItems || []), menuItem]\n return this\n }\n\n /**\n * Add hooks to plugin\n */\n addHooks(hooks: PluginHook[]): PluginBuilder {\n this.plugin.hooks = [...(this.plugin.hooks || []), ...hooks]\n return this\n }\n\n /**\n * Add a single hook to plugin\n */\n addHook(name: string, handler: any, options?: {\n priority?: number\n description?: string\n }): PluginBuilder {\n const hook: PluginHook = {\n name,\n handler,\n ...options\n }\n this.plugin.hooks = [...(this.plugin.hooks || []), hook]\n return this\n }\n\n /**\n * Add lifecycle hooks\n */\n lifecycle(hooks: {\n install?: Plugin['install']\n uninstall?: Plugin['uninstall']\n activate?: Plugin['activate']\n deactivate?: Plugin['deactivate']\n configure?: Plugin['configure']\n }): PluginBuilder {\n Object.assign(this.plugin, hooks)\n return this\n }\n\n /**\n * Build the plugin\n */\n build(): Plugin {\n // Validate required fields\n if (!this.plugin.name || !this.plugin.version) {\n throw new Error('Plugin name and version are required')\n }\n\n return this.plugin as Plugin\n }\n}\n\n/**\n * Helper functions for common plugin patterns\n */\nexport class PluginHelpers {\n /**\n * Create a REST API route for a model\n */\n static createModelAPI(modelName: string, options?: {\n basePath?: string\n permissions?: {\n read?: string[]\n write?: string[]\n delete?: string[]\n }\n }): Hono {\n const app = new Hono()\n const basePath = options?.basePath || `/${modelName.toLowerCase()}`\n\n // GET /models - List all\n app.get('/', async (c) => {\n // Implementation would depend on the model service\n return c.json({ message: `List ${modelName} items` })\n })\n\n // GET /models/:id - Get by ID\n app.get('/:id', async (c) => {\n const id = c.req.param('id')\n return c.json({ message: `Get ${modelName} with ID: ${id}` })\n })\n\n // POST /models - Create new\n app.post('/', async (c) => {\n return c.json({ message: `Create new ${modelName}` })\n })\n\n // PUT /models/:id - Update\n app.put('/:id', async (c) => {\n const id = c.req.param('id')\n return c.json({ message: `Update ${modelName} with ID: ${id}` })\n })\n\n // DELETE /models/:id - Delete\n app.delete('/:id', async (c) => {\n const id = c.req.param('id')\n return c.json({ message: `Delete ${modelName} with ID: ${id}` })\n })\n\n return app\n }\n\n /**\n * Create an admin CRUD interface for a model\n */\n static createAdminInterface(modelName: string, options?: {\n icon?: string\n permissions?: string[]\n fields?: Array<{\n name: string\n type: string\n label: string\n required?: boolean\n }>\n }): {\n pages: PluginAdminPage[]\n menuItems: PluginMenuItem[]\n } {\n const basePath = `/admin/${modelName.toLowerCase()}`\n const displayName = modelName.charAt(0).toUpperCase() + modelName.slice(1)\n\n const pages: PluginAdminPage[] = [\n {\n path: basePath,\n title: `${displayName} List`,\n component: `${modelName}List`,\n permissions: options?.permissions,\n icon: options?.icon\n },\n {\n path: `${basePath}/new`,\n title: `New ${displayName}`,\n component: `${modelName}Form`,\n permissions: options?.permissions\n },\n {\n path: `${basePath}/:id`,\n title: `Edit ${displayName}`,\n component: `${modelName}Form`,\n permissions: options?.permissions\n }\n ]\n\n const menuItems: PluginMenuItem[] = [\n {\n label: displayName,\n path: basePath,\n icon: options?.icon,\n permissions: options?.permissions\n }\n ]\n\n return { pages, menuItems }\n }\n\n /**\n * Create a database migration for a model\n */\n static createMigration(tableName: string, fields: Array<{\n name: string\n type: 'TEXT' | 'INTEGER' | 'REAL' | 'BLOB'\n nullable?: boolean\n primaryKey?: boolean\n unique?: boolean\n defaultValue?: string\n }>): string {\n const columns = fields.map(field => {\n let definition = `${field.name} ${field.type}`\n \n if (field.primaryKey) definition += ' PRIMARY KEY'\n if (field.unique) definition += ' UNIQUE'\n if (!field.nullable && !field.primaryKey) definition += ' NOT NULL'\n if (field.defaultValue) definition += ` DEFAULT ${field.defaultValue}`\n \n return definition\n }).join(',\\n ')\n\n return `\nCREATE TABLE IF NOT EXISTS ${tableName} (\n ${columns},\n created_at INTEGER NOT NULL DEFAULT (strftime('%s', 'now')),\n updated_at INTEGER NOT NULL DEFAULT (strftime('%s', 'now'))\n);\n\nCREATE TRIGGER IF NOT EXISTS ${tableName}_updated_at\n AFTER UPDATE ON ${tableName}\nBEGIN\n UPDATE ${tableName} SET updated_at = strftime('%s', 'now') WHERE id = NEW.id;\nEND;\n `.trim()\n }\n\n /**\n * Create a Zod schema for a model\n */\n static createSchema(fields: Array<{\n name: string\n type: 'string' | 'number' | 'boolean' | 'date' | 'array' | 'object'\n optional?: boolean\n validation?: any\n }>): z.ZodSchema {\n const shape: Record<string, z.ZodTypeAny> = {}\n\n for (const field of fields) {\n let schema: z.ZodTypeAny\n\n switch (field.type) {\n case 'string':\n schema = z.string()\n break\n case 'number':\n schema = z.number()\n break\n case 'boolean':\n schema = z.boolean()\n break\n case 'date':\n schema = z.date()\n break\n case 'array':\n schema = z.array(z.any())\n break\n case 'object':\n schema = z.object({})\n break\n default:\n schema = z.any()\n }\n\n if (field.optional) {\n schema = schema.optional()\n }\n\n if (field.validation) {\n // Apply additional validation\n if (field.type === 'string' && field.validation.min) {\n schema = (schema as z.ZodString).min(field.validation.min)\n }\n if (field.type === 'string' && field.validation.max) {\n schema = (schema as z.ZodString).max(field.validation.max)\n }\n if (field.type === 'string' && field.validation.email) {\n schema = (schema as z.ZodString).email()\n }\n if (field.type === 'string' && field.validation.url) {\n schema = (schema as z.ZodString).url()\n }\n }\n\n shape[field.name] = schema\n }\n\n return z.object(shape)\n }\n}\n\n/**\n * Common plugin templates\n */\nexport class PluginTemplates {\n /**\n * Create a simple content type plugin\n */\n static contentType(name: string, fields: Array<{\n name: string\n type: string\n label: string\n required?: boolean\n }>): Plugin {\n const builder = PluginBuilder.create({\n name: `${name}-content-type`,\n version: '1.0.0',\n description: `${name} content type plugin`\n })\n\n // Create model\n const schema = PluginHelpers.createSchema(\n fields.map(f => ({\n name: f.name,\n type: f.type as any,\n optional: !f.required\n }))\n )\n\n const migration = PluginHelpers.createMigration(\n name.toLowerCase(),\n fields.map(f => ({\n name: f.name,\n type: 'TEXT',\n nullable: !f.required\n }))\n )\n\n builder.addModel(name, {\n tableName: name.toLowerCase(),\n schema,\n migrations: [migration],\n extendsContent: true\n })\n\n // Create API routes\n const apiRoutes = PluginHelpers.createModelAPI(name)\n builder.addRoute(`/api/${name.toLowerCase()}`, apiRoutes)\n\n // Create admin interface\n const { pages, menuItems } = PluginHelpers.createAdminInterface(name, {\n fields\n })\n builder.addAdminPages(pages)\n builder.addMenuItems(menuItems)\n\n return builder.build()\n }\n\n /**\n * Create an analytics plugin\n */\n static analytics(name: string, options?: {\n endpoints?: string[]\n dashboard?: boolean\n }): Plugin {\n const builder = PluginBuilder.create({\n name: `${name}-analytics`,\n version: '1.0.0',\n description: `${name} analytics plugin`\n })\n\n // Add middleware to track requests\n builder.addSingleMiddleware('analytics-tracker', async (c: any, next: any) => {\n const start = Date.now()\n await next()\n const duration = Date.now() - start\n \n // Log analytics data\n console.info(`Analytics: ${c.req.method} ${c.req.path} - ${duration}ms`)\n }, {\n global: true,\n priority: 1\n })\n\n // Add analytics API\n const analyticsAPI = new Hono()\n analyticsAPI.get('/stats', (c) => {\n return c.json({ message: 'Analytics stats' })\n })\n builder.addRoute('/api/analytics', analyticsAPI)\n\n // Add dashboard if requested\n if (options?.dashboard) {\n builder.addAdminPage(\n '/analytics',\n 'Analytics Dashboard',\n 'AnalyticsDashboard',\n {\n description: 'View analytics and statistics',\n icon: 'chart-bar'\n }\n )\n\n builder.addMenuItem('Analytics', '/admin/analytics', {\n icon: 'chart-bar',\n order: 100\n })\n }\n\n return builder.build()\n }\n}\n","import { Plugin } from '../../../types/plugin'\nimport { PluginBuilder } from '../../sdk/plugin-builder'\n\n/**\n * TinyMCE Rich Text Editor Plugin\n *\n * Provides WYSIWYG editing capabilities for richtext fields.\n * When active, this plugin injects the TinyMCE editor into all richtext field types.\n * When inactive, richtext fields fall back to plain textareas.\n */\n\nconst builder = PluginBuilder.create({\n name: 'tinymce-plugin',\n version: '1.0.0',\n description: 'Powerful WYSIWYG rich text editor for content creation'\n})\n\nbuilder.metadata({\n author: {\n name: 'SonicJS Team',\n email: 'team@sonicjs.com'\n },\n license: 'MIT',\n compatibility: '^2.0.0'\n})\n\nbuilder.lifecycle({\n activate: async () => {\n console.info('✅ TinyMCE plugin activated')\n },\n deactivate: async () => {\n console.info('❌ TinyMCE plugin deactivated')\n }\n})\n\nconst tinymcePlugin = builder.build() as Plugin\n\nexport default tinymcePlugin\n\n/**\n * Get TinyMCE CDN script tag\n * @param apiKey - Optional TinyMCE API key (defaults to 'no-api-key')\n * @returns HTML script tag for TinyMCE CDN\n */\nexport function getTinyMCEScript(apiKey: string = 'no-api-key'): string {\n return `<script src=\"https://cdn.tiny.cloud/1/${apiKey}/tinymce/6/tinymce.min.js\" referrerpolicy=\"origin\"></script>`\n}\n\n/**\n * Get TinyMCE initialization script\n * @param config - Optional configuration object\n * @returns JavaScript initialization code\n */\nexport function getTinyMCEInitScript(config?: {\n skin?: string\n defaultHeight?: number\n defaultToolbar?: string\n}): string {\n const skin = config?.skin || 'oxide-dark'\n const contentCss = skin.includes('dark') ? 'dark' : 'default'\n const defaultHeight = config?.defaultHeight || 300\n\n return `\n // Initialize TinyMCE for all richtext fields\n function initializeTinyMCE() {\n if (typeof tinymce !== 'undefined') {\n // Find all textareas that need TinyMCE\n document.querySelectorAll('.richtext-container textarea').forEach((textarea) => {\n // Skip if already initialized\n if (tinymce.get(textarea.id)) {\n return;\n }\n\n // Get configuration from data attributes\n const container = textarea.closest('.richtext-container');\n const height = container?.dataset.height || ${defaultHeight};\n const toolbar = container?.dataset.toolbar || 'full';\n\n tinymce.init({\n selector: '#' + textarea.id,\n skin: '${skin}',\n content_css: '${contentCss}',\n height: parseInt(height),\n menubar: false,\n plugins: [\n 'advlist', 'autolink', 'lists', 'link', 'image', 'charmap', 'preview',\n 'anchor', 'searchreplace', 'visualblocks', 'code', 'fullscreen',\n 'insertdatetime', 'media', 'table', 'help', 'wordcount'\n ],\n toolbar: toolbar === 'simple'\n ? 'bold italic underline | bullist numlist | link'\n : toolbar === 'minimal'\n ? 'bold italic | link'\n : 'undo redo | blocks | bold italic forecolor | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | removeformat | help',\n content_style: 'body { font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, Oxygen, Ubuntu, Cantarell, sans-serif; font-size: 14px }'\n });\n });\n }\n }\n\n // Initialize on DOMContentLoaded\n if (document.readyState === 'loading') {\n document.addEventListener('DOMContentLoaded', initializeTinyMCE);\n } else {\n // DOM already loaded, initialize immediately\n initializeTinyMCE();\n }\n\n // Also reinitialize after HTMX swaps (for dynamic content)\n document.addEventListener('htmx:afterSwap', function(event) {\n // Give the DOM a moment to settle\n setTimeout(initializeTinyMCE, 100);\n });\n `\n}\n\n/**\n * Check if TinyMCE plugin is active\n * @param pluginService - Plugin service instance\n * @returns Promise<boolean>\n */\nexport async function isTinyMCEActive(pluginService: any): Promise<boolean> {\n try {\n const status = await pluginService.getPluginStatus('tinymce-plugin')\n return status?.is_active === true\n } catch (error) {\n console.error('Error checking TinyMCE plugin status:', error)\n return false\n }\n}\n","/**\n * Quill Rich Text Editor Plugin\n *\n * Provides Quill editor integration for rich text editing in SonicJS\n * https://quilljs.com/\n */\n\nimport { PluginBuilder } from '../../sdk/plugin-builder'\nimport type { Plugin } from '@sonicjs-cms/core'\n\n/**\n * Quill Editor Configuration Options\n */\nexport interface QuillOptions {\n theme?: 'snow' | 'bubble'\n placeholder?: string\n height?: number\n toolbar?: 'full' | 'simple' | 'minimal' | string[][]\n modules?: Record<string, any>\n formats?: string[]\n}\n\n/**\n * Default Quill toolbar configurations\n */\nconst QUILL_TOOLBARS = {\n full: [\n [{ 'header': [1, 2, 3, 4, 5, 6, false] }],\n ['bold', 'italic', 'underline', 'strike'],\n [{ 'color': [] }, { 'background': [] }],\n [{ 'align': [] }],\n [{ 'list': 'ordered'}, { 'list': 'bullet' }],\n [{ 'indent': '-1'}, { 'indent': '+1' }],\n ['blockquote', 'code-block'],\n ['link', 'image', 'video'],\n ['clean']\n ],\n simple: [\n ['bold', 'italic', 'underline'],\n [{ 'list': 'ordered'}, { 'list': 'bullet' }],\n ['link']\n ],\n minimal: [\n ['bold', 'italic'],\n ['link']\n ]\n}\n\n/**\n * Render a Quill editor field\n * @param fieldId - The field ID\n * @param fieldName - The field name\n * @param value - The current value\n * @param options - Quill configuration options\n * @returns HTML string for the Quill editor field\n */\nexport function renderQuillField(\n fieldId: string,\n fieldName: string,\n value: string = '',\n options: QuillOptions = {}\n): string {\n const {\n theme = 'snow',\n placeholder = 'Enter content...',\n height = 300,\n toolbar = 'full'\n } = options\n\n // Escape HTML for hidden input\n const escapeHtml = (str: string) => {\n return str\n .replace(/&/g, '&')\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/\"/g, '"')\n .replace(/'/g, ''')\n }\n\n return `\n <div class=\"quill-editor-container\" data-field-id=\"${fieldId}\">\n <!-- Quill Editor Container -->\n <div\n id=\"${fieldId}-editor\"\n class=\"quill-editor bg-white dark:bg-zinc-900 text-zinc-900 dark:text-zinc-100\"\n data-theme=\"${theme}\"\n data-toolbar=\"${toolbar}\"\n data-placeholder=\"${placeholder}\"\n data-height=\"${height}\"\n >${value}</div>\n\n <!-- Hidden input to store the actual content for form submission -->\n <input\n type=\"hidden\"\n id=\"${fieldId}\"\n name=\"${fieldName}\"\n value=\"${escapeHtml(value)}\"\n >\n </div>\n `\n}\n\n/**\n * Generate Quill initialization script\n * @returns HTML script tag with Quill initialization code\n */\nexport function getQuillInitScript(): string {\n return `\n <script>\n // Global Quill initialization function\n window.initializeQuillEditors = function() {\n console.log('[Quill] initializeQuillEditors called');\n if (typeof Quill === 'undefined') {\n console.warn('[Quill] Quill is not loaded yet. Retrying...');\n setTimeout(window.initializeQuillEditors, 100);\n return;\n }\n\n console.log('[Quill] Quill is loaded, searching for editors...');\n // Find all Quill editor containers that haven't been initialized\n const containers = document.querySelectorAll('.quill-editor-container');\n console.log('[Quill] Found', containers.length, 'editor containers');\n\n containers.forEach((container, index) => {\n console.log('[Quill] Processing container', index);\n try {\n const editorDiv = container.querySelector('.quill-editor');\n if (!editorDiv || editorDiv.classList.contains('ql-container')) {\n return; // Already initialized or invalid\n }\n\n const fieldId = container.getAttribute('data-field-id');\n const hiddenInput = document.getElementById(fieldId);\n const theme = editorDiv.getAttribute('data-theme') || 'snow';\n const toolbarPreset = editorDiv.getAttribute('data-toolbar') || 'full';\n const placeholder = editorDiv.getAttribute('data-placeholder') || 'Enter content...';\n const height = parseInt(editorDiv.getAttribute('data-height') || '300');\n\n // Get toolbar configuration\n const toolbarConfig = ${JSON.stringify(QUILL_TOOLBARS)};\n const toolbar = toolbarConfig[toolbarPreset] || toolbarConfig.full;\n\n // Initialize Quill\n const quill = new Quill('#' + editorDiv.id, {\n theme: theme,\n placeholder: placeholder,\n modules: {\n toolbar: toolbar\n },\n formats: [\n 'header', 'bold', 'italic', 'underline', 'strike',\n 'color', 'background', 'align',\n 'list', 'bullet', 'indent',\n 'blockquote', 'code-block',\n 'link', 'image', 'video'\n ]\n });\n\n // Set editor height\n const editorElement = editorDiv.querySelector('.ql-editor');\n if (editorElement) {\n editorElement.style.minHeight = height + 'px';\n }\n\n // Sync content to hidden input on change\n quill.on('text-change', function() {\n const html = quill.root.innerHTML;\n if (hiddenInput) {\n hiddenInput.value = html;\n }\n });\n\n // Store quill instance for potential later access\n editorDiv.quillInstance = quill;\n console.log('[Quill] Successfully initialized editor', index);\n } catch (error) {\n console.error('[Quill] Error initializing editor', index, ':', error);\n }\n });\n console.log('[Quill] Initialization complete');\n };\n\n // Initialize on DOM ready\n if (document.readyState === 'loading') {\n document.addEventListener('DOMContentLoaded', window.initializeQuillEditors);\n } else {\n window.initializeQuillEditors();\n }\n\n // Re-initialize after HTMX swaps\n if (typeof htmx !== 'undefined') {\n document.body.addEventListener('htmx:afterSwap', window.initializeQuillEditors);\n }\n </script>\n `\n}\n\n/**\n * Generate Quill CDN links\n * @param version - Quill version (default: 2.0.2)\n * @returns HTML script and link tags for Quill CDN\n */\nexport function getQuillCDN(version: string = '2.0.2'): string {\n return `\n <!-- Quill Editor CSS -->\n <link href=\"https://cdn.jsdelivr.net/npm/quill@${version}/dist/quill.snow.css\" rel=\"stylesheet\">\n <link href=\"https://cdn.jsdelivr.net/npm/quill@${version}/dist/quill.bubble.css\" rel=\"stylesheet\">\n\n <!-- Quill Editor JS -->\n <script src=\"https://cdn.jsdelivr.net/npm/quill@${version}/dist/quill.js\"></script>\n\n <!-- Quill Dark Mode Styles -->\n <style>\n /* Dark mode styles for Quill editor */\n .dark .ql-toolbar {\n background-color: #18181b !important;\n border-color: #3f3f46 !important;\n }\n\n .dark .ql-toolbar button,\n .dark .ql-toolbar .ql-picker-label {\n color: #e4e4e7 !important;\n }\n\n .dark .ql-toolbar button:hover,\n .dark .ql-toolbar .ql-picker-label:hover {\n color: #fff !important;\n }\n\n .dark .ql-toolbar button.ql-active,\n .dark .ql-toolbar .ql-picker-label.ql-active {\n color: #3b82f6 !important;\n }\n\n .dark .ql-stroke {\n stroke: #e4e4e7 !important;\n }\n\n .dark .ql-fill {\n fill: #e4e4e7 !important;\n }\n\n .dark .ql-picker-options {\n background-color: #18181b !important;\n border-color: #3f3f46 !important;\n }\n\n .dark .ql-picker-item:hover {\n background-color: #27272a !important;\n }\n\n .dark .ql-container {\n background-color: #09090b !important;\n border-color: #3f3f46 !important;\n color: #e4e4e7 !important;\n }\n\n .dark .ql-editor {\n color: #e4e4e7 !important;\n }\n\n .dark .ql-editor.ql-blank::before {\n color: #71717a !important;\n }\n\n /* Improve contrast for dark mode */\n .dark .ql-snow .ql-stroke {\n stroke: #e4e4e7 !important;\n }\n\n .dark .ql-snow .ql-stroke.ql-fill {\n fill: #e4e4e7 !important;\n }\n\n .dark .ql-snow .ql-fill {\n fill: #e4e4e7 !important;\n }\n\n .dark .ql-snow .ql-picker-options {\n background-color: #18181b !important;\n }\n\n .dark .ql-snow .ql-picker-item:hover {\n color: #3b82f6 !important;\n }\n </style>\n `\n}\n\n/**\n * Create the Quill Editor Plugin\n */\nexport function createQuillEditorPlugin(): Plugin {\n const builder = PluginBuilder.create({\n name: 'quill-editor',\n version: '1.0.0',\n description: 'Quill rich text editor integration for SonicJS'\n })\n\n // Add plugin metadata\n builder.metadata({\n author: {\n name: 'SonicJS Team',\n email: 'team@sonicjs.com'\n },\n license: 'MIT',\n compatibility: '^2.0.0'\n })\n\n // Add lifecycle hooks\n builder.lifecycle({\n activate: async () => {\n console.info('✅ Quill Editor plugin activated')\n },\n\n deactivate: async () => {\n console.info('❌ Quill Editor plugin deactivated')\n }\n })\n\n return builder.build() as Plugin\n}\n\n// Export the plugin instance\nexport const quillEditorPlugin = createQuillEditorPlugin()\n","import { Plugin } from '../../../types/plugin'\nimport { PluginBuilder } from '../../sdk/plugin-builder'\n\n/**\n * EasyMDE Markdown Editor Plugin\n *\n * Provides markdown editing capabilities for richtext fields.\n * When active, this plugin injects the EasyMDE editor into all richtext field types.\n * When inactive, richtext fields fall back to plain textareas.\n */\n\nconst builder = PluginBuilder.create({\n name: 'easy-mdx',\n version: '1.0.0',\n description: 'Lightweight markdown editor with live preview'\n})\n\nbuilder.metadata({\n author: {\n name: 'SonicJS Team',\n email: 'team@sonicjs.com'\n },\n license: 'MIT',\n compatibility: '^2.0.0'\n})\n\nbuilder.lifecycle({\n activate: async () => {\n console.info('✅ EasyMDE editor plugin activated')\n },\n deactivate: async () => {\n console.info('❌ EasyMDE editor plugin deactivated')\n }\n})\n\nconst easyMdxPlugin = builder.build() as Plugin\n\nexport default easyMdxPlugin\n\n/**\n * Get EasyMDE CDN script tags\n * @returns HTML script and style tags for EasyMDE\n */\nexport function getMDXEditorScripts(): string {\n return `\n <!-- EasyMDE Markdown Editor -->\n <link rel=\"stylesheet\" href=\"https://unpkg.com/easymde/dist/easymde.min.css\">\n <script src=\"https://unpkg.com/easymde/dist/easymde.min.js\"></script>\n <style>\n /* Dark mode styling for EasyMDE */\n .EasyMDEContainer {\n background-color: #1e293b;\n }\n\n .EasyMDEContainer .CodeMirror {\n background-color: #1e293b;\n color: #e2e8f0;\n border-color: #334155;\n }\n\n .EasyMDEContainer .CodeMirror-scroll {\n background-color: #1e293b;\n }\n\n .EasyMDEContainer .CodeMirror-cursor {\n border-left-color: #e2e8f0;\n }\n\n .EasyMDEContainer .CodeMirror-gutters {\n background-color: #0f172a;\n border-right-color: #334155;\n }\n\n .EasyMDEContainer .CodeMirror-linenumber {\n color: #64748b;\n }\n\n .editor-toolbar {\n background-color: #0f172a;\n border-color: #334155;\n }\n\n .editor-toolbar button {\n color: #94a3b8 !important;\n }\n\n .editor-toolbar button:hover,\n .editor-toolbar button.active {\n background-color: #334155;\n border-color: #475569;\n color: #e2e8f0 !important;\n }\n\n .editor-toolbar i.separator {\n border-left-color: #334155;\n border-right-color: #334155;\n }\n\n .editor-statusbar {\n background-color: #0f172a;\n color: #64748b;\n border-top-color: #334155;\n }\n\n .editor-preview,\n .editor-preview-side {\n background-color: #1e293b;\n color: #e2e8f0;\n }\n\n .CodeMirror-selected {\n background-color: #334155 !important;\n }\n\n .CodeMirror-focused .CodeMirror-selected {\n background-color: #475569 !important;\n }\n\n /* Syntax highlighting for dark mode */\n .cm-header {\n color: #60a5fa;\n }\n\n .cm-strong {\n color: #fbbf24;\n }\n\n .cm-em {\n color: #a78bfa;\n }\n\n .cm-link {\n color: #34d399;\n }\n\n .cm-url {\n color: #34d399;\n }\n\n .cm-quote {\n color: #94a3b8;\n font-style: italic;\n }\n\n .cm-comment {\n color: #64748b;\n }\n </style>\n `\n}\n\n/**\n * Get EasyMDE initialization script\n * @param config - Optional configuration object\n * @returns JavaScript initialization code\n */\nexport function getMDXEditorInitScript(config?: {\n defaultHeight?: number\n toolbar?: string\n placeholder?: string\n}): string {\n const defaultHeight = config?.defaultHeight || 400\n const toolbar = config?.toolbar || 'full'\n const placeholder = config?.placeholder || 'Start writing your content...'\n\n return `\n // Initialize EasyMDE (Markdown Editor) for all richtext fields\n function initializeMDXEditor() {\n if (typeof EasyMDE === 'undefined') {\n console.warn('EasyMDE not loaded yet, retrying...');\n setTimeout(initializeMDXEditor, 100);\n return;\n }\n\n // Find all textareas that need EasyMDE\n document.querySelectorAll('.richtext-container textarea').forEach((textarea) => {\n // Skip if already initialized\n if (textarea.dataset.mdxeditorInitialized === 'true') {\n return;\n }\n\n // Mark as initialized\n textarea.dataset.mdxeditorInitialized = 'true';\n\n // Get configuration from data attributes\n const container = textarea.closest('.richtext-container');\n const height = container?.dataset.height || ${defaultHeight};\n const editorToolbar = container?.dataset.toolbar || '${toolbar}';\n\n // Initialize EasyMDE\n try {\n const toolbarButtons = editorToolbar === 'minimal'\n ? ['bold', 'italic', 'heading', '|', 'quote', 'unordered-list', 'ordered-list', '|', 'link', 'preview']\n : ['bold', 'italic', 'heading', '|', 'quote', 'unordered-list', 'ordered-list', '|', 'link', 'image', 'table', '|', 'preview', 'side-by-side', 'fullscreen', '|', 'guide'];\n\n const easyMDE = new EasyMDE({\n element: textarea,\n placeholder: '${placeholder}',\n spellChecker: false,\n minHeight: height + 'px',\n toolbar: toolbarButtons,\n status: ['lines', 'words', 'cursor'],\n renderingConfig: {\n singleLineBreaks: false,\n codeSyntaxHighlighting: true\n }\n });\n\n // Store reference to editor instance\n textarea.easyMDEInstance = easyMDE;\n\n console.log('EasyMDE initialized for field:', textarea.id || textarea.name);\n } catch (error) {\n console.error('Error initializing EasyMDE:', error);\n // Show textarea as fallback\n textarea.style.display = 'block';\n }\n });\n }\n\n // Initialize on DOMContentLoaded\n if (document.readyState === 'loading') {\n document.addEventListener('DOMContentLoaded', initializeMDXEditor);\n } else {\n // DOM already loaded, initialize immediately\n initializeMDXEditor();\n }\n\n // Also reinitialize after HTMX swaps (for dynamic content)\n document.addEventListener('htmx:afterSwap', function(event) {\n // Give the DOM a moment to settle\n setTimeout(initializeMDXEditor, 100);\n });\n `\n}\n\n/**\n * Check if EasyMDE editor plugin is active\n * @param pluginService - Plugin service instance\n * @returns Promise<boolean>\n */\nexport async function isEasyMdxActive(pluginService: any): Promise<boolean> {\n try {\n const status = await pluginService.getPluginStatus('easy-mdx')\n return status?.is_active === true\n } catch (error) {\n console.error('Error checking EasyMDE editor plugin status:', error)\n return false\n }\n}\n","import { renderAdminLayoutCatalyst, AdminLayoutCatalystData } from '../layouts/admin-layout-catalyst.template'\nimport { renderPagination, PaginationData } from '../pagination.template'\nimport { renderTable, TableData, TableColumn } from '../table.template'\nimport type { FilterBarData } from '../filter-bar.template'\nimport { renderConfirmationDialog, getConfirmationDialogScript } from '../confirmation-dialog.template'\n\nexport interface ContentItem {\n id: string\n title: string\n slug: string\n modelName: string\n statusBadge: string\n authorName: string\n formattedDate: string\n availableActions: string[]\n}\n\nexport interface ContentListPageData {\n modelName: string\n status: string\n page: number\n search?: string\n models: Array<{\n name: string\n displayName: string\n }>\n contentItems: ContentItem[]\n totalItems: number\n itemsPerPage: number\n user?: {\n name: string\n email: string\n role: string\n }\n version?: string\n}\n\nexport function renderContentListPage(data: ContentListPageData): string {\n // Build current URL parameters to pass to edit page\n const urlParams = new URLSearchParams()\n if (data.modelName && data.modelName !== 'all') urlParams.set('model', data.modelName)\n if (data.status && data.status !== 'all') urlParams.set('status', data.status)\n if (data.search) urlParams.set('search', data.search)\n if (data.page && data.page !== 1) urlParams.set('page', data.page.toString())\n const currentParams = urlParams.toString()\n\n // Check if filters are active (not in default state)\n const hasActiveFilters = data.modelName !== 'all' || data.status !== 'all' || !!data.search\n\n // Prepare filter bar data\n const filterBarData: FilterBarData = {\n filters: [\n {\n name: 'model',\n label: 'Model',\n options: [\n { value: 'all', label: 'All Models', selected: data.modelName === 'all' },\n ...data.models.map(model => ({\n value: model.name,\n label: model.displayName,\n selected: data.modelName === model.name\n }))\n ]\n },\n {\n name: 'status',\n label: 'Status',\n options: [\n { value: 'all', label: 'All Status', selected: data.status === 'all' },\n { value: 'draft', label: 'Draft', selected: data.status === 'draft' },\n { value: 'review', label: 'Under Review', selected: data.status === 'review' },\n { value: 'scheduled', label: 'Scheduled', selected: data.status === 'scheduled' },\n { value: 'published', label: 'Published', selected: data.status === 'published' },\n { value: 'archived', label: 'Archived', selected: data.status === 'archived' },\n { value: 'deleted', label: 'Deleted', selected: data.status === 'deleted' }\n ]\n }\n ],\n actions: [\n {\n label: 'Refresh',\n className: 'btn-secondary',\n onclick: 'location.reload()'\n }\n ],\n bulkActions: [\n { label: 'Publish', value: 'publish', icon: 'check-circle' },\n { label: 'Unpublish', value: 'unpublish', icon: 'x-circle' },\n { label: 'Delete', value: 'delete', icon: 'trash', className: 'text-pink-600' }\n ]\n }\n\n // Prepare table data\n const tableColumns: TableColumn[] = [\n {\n key: 'title',\n label: 'Title',\n sortable: true,\n sortType: 'string',\n render: (value, row) => `\n <div class=\"flex items-center\">\n <div>\n <div class=\"text-sm font-medium text-zinc-950 dark:text-white\">\n <a href=\"/admin/content/${row.id}/edit${currentParams ? `?ref=${encodeURIComponent(currentParams)}` : ''}\" class=\"hover:text-blue-600 dark:hover:text-blue-400 transition-colors\">${row.title}</a>\n </div>\n <div class=\"text-sm text-zinc-500 dark:text-zinc-400\">${row.slug}</div>\n </div>\n </div>\n `\n },\n {\n key: 'modelName',\n label: 'Model',\n sortable: true,\n sortType: 'string',\n className: 'text-sm text-zinc-500 dark:text-zinc-400'\n },\n {\n key: 'statusBadge',\n label: 'Status',\n sortable: true,\n sortType: 'string',\n render: (value) => value\n },\n {\n key: 'authorName',\n label: 'Author',\n sortable: true,\n sortType: 'string',\n className: 'text-sm text-zinc-500 dark:text-zinc-400'\n },\n {\n key: 'formattedDate',\n label: 'Updated',\n sortable: true,\n sortType: 'date',\n className: 'text-sm text-zinc-500 dark:text-zinc-400'\n },\n {\n key: 'actions',\n label: 'Actions',\n sortable: false,\n className: 'text-sm font-medium',\n render: (value, row) => `\n <div class=\"flex space-x-2\">\n <button\n class=\"inline-flex items-center justify-center p-1.5 rounded-lg bg-cyan-50 dark:bg-cyan-500/10 text-cyan-700 dark:text-cyan-400 ring-1 ring-inset ring-cyan-600/20 dark:ring-cyan-500/20 hover:bg-cyan-100 dark:hover:bg-cyan-500/20 transition-colors\"\n onclick=\"window.location.href='/admin/content/${row.id}/edit${currentParams ? `?ref=${encodeURIComponent(currentParams)}` : ''}'\"\n title=\"Edit\"\n >\n <svg class=\"h-4 w-4\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M15.232 5.232l3.536 3.536m-2.036-5.036a2.5 2.5 0 113.536 3.536L6.5 21.036H3v-3.572L16.732 3.732z\"/>\n </svg>\n </button>\n <button\n class=\"inline-flex items-center justify-center p-1.5 rounded-lg bg-purple-50 dark:bg-purple-500/10 text-purple-700 dark:text-purple-400 ring-1 ring-inset ring-purple-600/20 dark:ring-purple-500/20 hover:bg-purple-100 dark:hover:bg-purple-500/20 transition-colors\"\n onclick=\"window.open('/api/content/${row.id}', '_blank')\"\n title=\"View API\"\n >\n <svg class=\"h-4 w-4\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M10 20l4-16m4 4l4 4-4 4M6 16l-4-4 4-4\"/>\n </svg>\n </button>\n <button\n class=\"inline-flex items-center justify-center p-1.5 rounded-lg bg-red-50 dark:bg-red-500/10 text-red-700 dark:text-red-400 ring-1 ring-inset ring-red-600/20 dark:ring-red-500/20 hover:bg-red-100 dark:hover:bg-red-500/20 transition-colors\"\n hx-delete=\"/admin/content/${row.id}\"\n hx-confirm=\"Are you sure you want to delete this content item?\"\n hx-target=\"#content-list\"\n hx-swap=\"outerHTML\"\n title=\"Delete\"\n >\n <svg class=\"h-4 w-4\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16\"/>\n </svg>\n </button>\n </div>\n `\n }\n ]\n\n const tableData: TableData<ContentItem> = {\n tableId: 'content-table',\n columns: tableColumns,\n rows: data.contentItems,\n selectable: true,\n rowClickable: true,\n rowClickUrl: (row: ContentItem) => `/admin/content/${row.id}/edit${currentParams ? `?ref=${encodeURIComponent(currentParams)}` : ''}`,\n emptyMessage: 'No content found. Create your first content item to get started.'\n }\n\n // Prepare pagination data\n const totalPages = Math.ceil(data.totalItems / data.itemsPerPage)\n const startItem = (data.page - 1) * data.itemsPerPage + 1\n const endItem = Math.min(data.page * data.itemsPerPage, data.totalItems)\n\n const paginationData: PaginationData = {\n currentPage: data.page,\n totalPages,\n totalItems: data.totalItems,\n itemsPerPage: data.itemsPerPage,\n startItem,\n endItem,\n baseUrl: '/admin/content',\n queryParams: {\n model: data.modelName,\n status: data.status,\n ...(data.search ? { search: data.search } : {})\n },\n showPageSizeSelector: true,\n pageSizeOptions: [10, 20, 50, 100]\n }\n\n // Generate page content\n const pageContent = `\n <div>\n <!-- Header -->\n <div class=\"flex flex-col sm:flex-row sm:items-center sm:justify-between mb-6\">\n <div>\n <h1 class=\"text-2xl/8 font-semibold text-zinc-950 dark:text-white sm:text-xl/8\">Content Management</h1>\n <p class=\"mt-2 text-sm/6 text-zinc-500 dark:text-zinc-400\">Manage and organize your content items</p>\n </div>\n <div class=\"mt-4 sm:mt-0 sm:ml-16 sm:flex-none\">\n <a href=\"/admin/content/new\" class=\"inline-flex items-center justify-center rounded-lg bg-zinc-950 dark:bg-white px-3.5 py-2.5 text-sm font-semibold text-white dark:text-zinc-950 hover:bg-zinc-800 dark:hover:bg-zinc-100 transition-colors shadow-sm\">\n <svg class=\"-ml-0.5 mr-1.5 h-5 w-5\" viewBox=\"0 0 20 20\" fill=\"currentColor\">\n <path d=\"M10.75 4.75a.75.75 0 00-1.5 0v4.5h-4.5a.75.75 0 000 1.5h4.5v4.5a.75.75 0 001.5 0v-4.5h4.5a.75.75 0 000-1.5h-4.5v-4.5z\" />\n </svg>\n New Content\n </a>\n </div>\n </div>\n <!-- Filters -->\n <div class=\"relative rounded-xl mb-6\">\n <!-- Gradient Background -->\n <div class=\"absolute inset-0 bg-gradient-to-r from-cyan-500/10 via-blue-500/10 to-purple-500/10 dark:from-cyan-400/20 dark:via-blue-400/20 dark:to-purple-400/20 rounded-xl\"></div>\n\n <div class=\"relative bg-white/80 dark:bg-zinc-900/80 backdrop-blur-xl shadow-sm ring-1 ring-zinc-950/5 dark:ring-white/10 rounded-xl\">\n <div class=\"px-6 py-5\">\n <div class=\"flex items-center justify-between\">\n <div class=\"flex items-center space-x-4\">\n <!-- Search Input -->\n <div>\n <label class=\"block text-sm font-medium text-zinc-950 dark:text-white mb-2\">Search</label>\n <form onsubmit=\"performContentSearch(event)\" class=\"flex items-center space-x-2\">\n <div class=\"relative group\">\n <input\n type=\"text\"\n name=\"search\"\n id=\"content-search-input\"\n value=\"${data.search || ''}\"\n oninput=\"toggleContentClearButton()\"\n placeholder=\"Search content...\"\n class=\"rounded-full bg-white/90 dark:bg-zinc-800/90 backdrop-blur-sm px-4 py-2.5 pl-11 pr-10 text-sm w-72 text-zinc-950 dark:text-white border-2 border-cyan-200/50 dark:border-cyan-700/50 placeholder:text-zinc-400 dark:placeholder:text-zinc-500 focus:outline-none focus:border-cyan-500 dark:focus:border-cyan-400 focus:bg-white dark:focus:bg-zinc-800 focus:shadow-lg focus:shadow-cyan-500/20 dark:focus:shadow-cyan-400/20 transition-all duration-300\"\n >\n <div class=\"absolute left-3.5 top-2.5 flex items-center justify-center w-5 h-5 rounded-full bg-gradient-to-br from-cyan-400 to-blue-500 dark:from-cyan-300 dark:to-blue-400 opacity-90 group-focus-within:opacity-100 transition-opacity\">\n <svg class=\"h-3 w-3 text-white\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\" stroke-width=\"2.5\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z\"/>\n </svg>\n </div>\n <button\n type=\"button\"\n id=\"clear-content-search\"\n onclick=\"clearContentSearch()\"\n class=\"${data.search ? '' : 'hidden'} absolute right-3 top-3 flex items-center justify-center w-5 h-5 rounded-full bg-zinc-400/20 dark:bg-zinc-500/20 hover:bg-zinc-400/30 dark:hover:bg-zinc-500/30 transition-colors\"\n >\n <svg class=\"h-3 w-3 text-zinc-600 dark:text-zinc-400\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\" stroke-width=\"2.5\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M6 18L18 6M6 6l12 12\"/>\n </svg>\n </button>\n </div>\n <button\n type=\"submit\"\n class=\"inline-flex items-center gap-x-1.5 px-4 py-2.5 bg-gradient-to-r from-cyan-500 to-blue-500 dark:from-cyan-400 dark:to-blue-400 text-white text-sm font-medium rounded-full hover:from-cyan-600 hover:to-blue-600 dark:hover:from-cyan-500 dark:hover:to-blue-500 shadow-md hover:shadow-lg transition-all duration-200\"\n >\n <svg class=\"h-4 w-4\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\" stroke-width=\"2.5\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z\"/>\n </svg>\n Search\n </button>\n </form>\n <script>\n function performContentSearch(event) {\n event.preventDefault();\n const searchInput = document.getElementById('content-search-input');\n const value = searchInput.value.trim();\n const params = new URLSearchParams(window.location.search);\n if (value) {\n params.set('search', value);\n } else {\n params.delete('search');\n }\n params.set('page', '1');\n window.location.href = window.location.pathname + '?' + params.toString();\n }\n\n function clearContentSearch() {\n const params = new URLSearchParams(window.location.search);\n params.delete('search');\n params.set('page', '1');\n window.location.href = window.location.pathname + (params.toString() ? '?' + params.toString() : '');\n }\n\n function toggleContentClearButton() {\n const searchInput = document.getElementById('content-search-input');\n const clearButton = document.getElementById('clear-content-search');\n if (searchInput.value.trim()) {\n clearButton.classList.remove('hidden');\n } else {\n clearButton.classList.add('hidden');\n }\n }\n\n function updateContentFilters(filterName, filterValue) {\n const params = new URLSearchParams(window.location.search);\n params.set(filterName, filterValue);\n params.set('page', '1');\n window.location.href = window.location.pathname + '?' + params.toString();\n }\n\n function clearAllFilters() {\n window.location.href = window.location.pathname;\n }\n </script>\n </div>\n\n ${filterBarData.filters.map(filter => {\n const selectedOption = filter.options.find(opt => opt.selected);\n const selectedColor = selectedOption?.color || 'cyan';\n const colorMap: Record<string, string> = {\n 'cyan': 'bg-cyan-400 dark:bg-cyan-400',\n 'lime': 'bg-lime-400 dark:bg-lime-400',\n 'pink': 'bg-pink-400 dark:bg-pink-400',\n 'purple': 'bg-purple-400 dark:bg-purple-400',\n 'amber': 'bg-amber-400 dark:bg-amber-400',\n 'zinc': 'bg-zinc-400 dark:bg-zinc-400'\n };\n\n return `\n <div>\n <label class=\"block text-sm/6 font-medium text-zinc-950 dark:text-white\">${filter.label}</label>\n <div class=\"mt-2 grid grid-cols-1\">\n <div class=\"col-start-1 row-start-1 flex items-center gap-3 pl-3 pr-8 pointer-events-none\">\n ${filter.name === 'status' ? `<span class=\"inline-block size-2 shrink-0 rounded-full border border-transparent ${colorMap[selectedColor]}\"></span>` : ''}\n </div>\n <select\n name=\"${filter.name}\"\n onchange=\"updateContentFilters('${filter.name}', this.value)\"\n class=\"col-start-1 row-start-1 w-full appearance-none rounded-md bg-white/5 dark:bg-white/5 py-1.5 ${filter.name === 'status' ? 'pl-8' : 'pl-3'} pr-8 text-base text-zinc-950 dark:text-white outline outline-1 -outline-offset-1 outline-cyan-500/30 dark:outline-cyan-400/30 *:bg-white dark:*:bg-zinc-800 focus-visible:outline focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-cyan-500 dark:focus-visible:outline-cyan-400 sm:text-sm/6 min-w-48\"\n >\n ${filter.options.map(opt => `\n <option value=\"${opt.value}\" ${opt.selected ? 'selected' : ''}>${opt.label}</option>\n `).join('')}\n </select>\n <svg viewBox=\"0 0 16 16\" fill=\"currentColor\" data-slot=\"icon\" aria-hidden=\"true\" class=\"pointer-events-none col-start-1 row-start-1 mr-2 size-5 self-center justify-self-end text-cyan-600 dark:text-cyan-400 sm:size-4\">\n <path d=\"M4.22 6.22a.75.75 0 0 1 1.06 0L8 8.94l2.72-2.72a.75.75 0 1 1 1.06 1.06l-3.25 3.25a.75.75 0 0 1-1.06 0L4.22 7.28a.75.75 0 0 1 0-1.06Z\" clip-rule=\"evenodd\" fill-rule=\"evenodd\" />\n </svg>\n </div>\n </div>\n `}).join('')}\n\n <!-- Clear Filters Button -->\n ${hasActiveFilters ? `\n <div>\n <label class=\"block text-sm/6 font-medium text-zinc-950 dark:text-white mb-2\"> </label>\n <button\n onclick=\"clearAllFilters()\"\n class=\"inline-flex items-center gap-x-1.5 px-3 py-2 bg-pink-50 dark:bg-pink-500/10 text-pink-700 dark:text-pink-300 text-sm font-medium rounded-md ring-1 ring-inset ring-pink-600/20 dark:ring-pink-500/20 hover:bg-pink-100 dark:hover:bg-pink-500/20 transition-colors\"\n >\n <svg class=\"h-4 w-4\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\" stroke-width=\"2\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M6 18L18 6M6 6l12 12\"/>\n </svg>\n Clear Filters\n </button>\n </div>\n ` : ''}\n </div>\n <div class=\"flex items-center gap-x-3\">\n <span class=\"text-sm/6 font-medium text-zinc-700 dark:text-zinc-300 px-3 py-1.5 rounded-full bg-white/60 dark:bg-zinc-800/60 backdrop-blur-sm\">${data.totalItems} ${data.totalItems === 1 ? 'item' : 'items'}</span>\n ${filterBarData.actions?.map(action => `\n <button\n ${action.onclick ? `onclick=\"${action.onclick}\"` : ''}\n ${action.hxGet ? `hx-get=\"${action.hxGet}\"` : ''}\n ${action.hxTarget ? `hx-target=\"${action.hxTarget}\"` : ''}\n class=\"inline-flex items-center gap-x-1.5 px-3 py-1.5 bg-white/90 dark:bg-zinc-800/90 backdrop-blur-sm text-zinc-950 dark:text-white text-sm font-medium rounded-full ring-1 ring-inset ring-cyan-200/50 dark:ring-cyan-700/50 hover:bg-gradient-to-r hover:from-cyan-50 hover:to-blue-50 dark:hover:from-cyan-900/30 dark:hover:to-blue-900/30 hover:ring-cyan-300 dark:hover:ring-cyan-600 transition-all duration-200\"\n >\n ${action.label === 'Refresh' ? `\n <svg class=\"h-4 w-4\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15\"/>\n </svg>\n ` : ''}\n ${action.label}\n </button>\n `).join('') || ''}\n ${filterBarData.bulkActions && filterBarData.bulkActions.length > 0 ? `\n <div class=\"relative inline-block\" id=\"bulk-actions-dropdown\">\n <button\n id=\"bulk-actions-btn\"\n onclick=\"toggleBulkActionsDropdown()\"\n class=\"inline-flex items-center gap-x-1.5 px-3 py-1.5 bg-zinc-100/60 dark:bg-zinc-800/60 backdrop-blur-sm text-zinc-400 dark:text-zinc-600 text-sm font-medium rounded-full ring-1 ring-inset ring-zinc-200/50 dark:ring-zinc-700/50 cursor-not-allowed\"\n disabled\n >\n Bulk Actions\n <svg viewBox=\"0 0 20 20\" fill=\"currentColor\" class=\"size-4\">\n <path d=\"M5.22 8.22a.75.75 0 0 1 1.06 0L10 11.94l3.72-3.72a.75.75 0 1 1 1.06 1.06l-4.25 4.25a.75.75 0 0 1-1.06 0L5.22 9.28a.75.75 0 0 1 0-1.06Z\" clip-rule=\"evenodd\" fill-rule=\"evenodd\" />\n </svg>\n </button>\n\n <div\n id=\"bulk-actions-menu\"\n class=\"hidden absolute right-0 mt-2 w-56 origin-top-right divide-y divide-zinc-200 dark:divide-white/10 rounded-lg bg-white dark:bg-zinc-900 shadow-xl ring-1 ring-zinc-950/5 dark:ring-white/10 z-50 transition-all duration-100 scale-95 opacity-0\"\n style=\"transition-behavior: allow-discrete;\"\n >\n <div class=\"py-1\">\n <button\n onclick=\"performBulkAction('publish')\"\n class=\"group/item flex w-full items-center px-4 py-2 text-sm text-zinc-700 dark:text-zinc-300 hover:bg-zinc-50 dark:hover:bg-white/5 hover:text-zinc-950 dark:hover:text-white transition-colors\"\n >\n <svg viewBox=\"0 0 20 20\" fill=\"currentColor\" class=\"mr-3 size-5 text-zinc-400 dark:text-zinc-500 group-hover/item:text-zinc-950 dark:group-hover/item:text-white\">\n <path fill-rule=\"evenodd\" d=\"M16.704 4.153a.75.75 0 0 1 .143 1.052l-8 10.5a.75.75 0 0 1-1.127.075l-4.5-4.5a.75.75 0 0 1 1.06-1.06l3.894 3.893 7.48-9.817a.75.75 0 0 1 1.05-.143Z\" clip-rule=\"evenodd\" />\n </svg>\n Publish Selected\n </button>\n <button\n onclick=\"performBulkAction('draft')\"\n class=\"group/item flex w-full items-center px-4 py-2 text-sm text-zinc-700 dark:text-zinc-300 hover:bg-zinc-50 dark:hover:bg-white/5 hover:text-zinc-950 dark:hover:text-white transition-colors\"\n >\n <svg viewBox=\"0 0 20 20\" fill=\"currentColor\" class=\"mr-3 size-5 text-zinc-400 dark:text-zinc-500 group-hover/item:text-zinc-950 dark:group-hover/item:text-white\">\n <path d=\"m5.433 13.917 1.262-3.155A4 4 0 0 1 7.58 9.42l6.92-6.918a2.121 2.121 0 0 1 3 3l-6.92 6.918c-.383.383-.84.685-1.343.886l-3.154 1.262a.5.5 0 0 1-.65-.65Z\" />\n <path d=\"M3.5 5.75c0-.69.56-1.25 1.25-1.25H10A.75.75 0 0 0 10 3H4.75A2.75 2.75 0 0 0 2 5.75v9.5A2.75 2.75 0 0 0 4.75 18h9.5A2.75 2.75 0 0 0 17 15.25V10a.75.75 0 0 0-1.5 0v5.25c0 .69-.56 1.25-1.25 1.25h-9.5c-.69 0-1.25-.56-1.25-1.25v-9.5Z\" />\n </svg>\n Move to Draft\n </button>\n </div>\n <div class=\"py-1\">\n <button\n onclick=\"performBulkAction('delete')\"\n class=\"group/item flex w-full items-center px-4 py-2 text-sm text-zinc-700 dark:text-zinc-300 hover:bg-red-50 dark:hover:bg-red-500/10 hover:text-red-600 dark:hover:text-red-400 transition-colors\"\n >\n <svg viewBox=\"0 0 20 20\" fill=\"currentColor\" class=\"mr-3 size-5 text-zinc-400 dark:text-zinc-500 group-hover/item:text-red-600 dark:group-hover/item:text-red-400\">\n <path fill-rule=\"evenodd\" d=\"M8.75 1A2.75 2.75 0 0 0 6 3.75v.443c-.795.077-1.584.176-2.365.298a.75.75 0 1 0 .23 1.482l.149-.022.841 10.518A2.75 2.75 0 0 0 7.596 19h4.807a2.75 2.75 0 0 0 2.742-2.53l.841-10.52.149.023a.75.75 0 0 0 .23-1.482A41.03 41.03 0 0 0 14 4.193V3.75A2.75 2.75 0 0 0 11.25 1h-2.5ZM10 4c.84 0 1.673.025 2.5.075V3.75c0-.69-.56-1.25-1.25-1.25h-2.5c-.69 0-1.25.56-1.25 1.25v.325C8.327 4.025 9.16 4 10 4ZM8.58 7.72a.75.75 0 0 0-1.5.06l.3 7.5a.75.75 0 1 0 1.5-.06l-.3-7.5Zm4.34.06a.75.75 0 1 0-1.5-.06l-.3 7.5a.75.75 0 1 0 1.5.06l.3-7.5Z\" clip-rule=\"evenodd\" fill-rule=\"evenodd\" />\n </svg>\n Delete Selected\n </button>\n </div>\n </div>\n </div>\n ` : ''}\n </div>\n </div>\n </div>\n </div>\n </div>\n \n <!-- Content List -->\n <div id=\"content-list\">\n ${renderTable(tableData)}\n ${renderPagination(paginationData)}\n </div>\n \n </div>\n \n <!-- Modals -->\n <div id=\"bulk-actions-modal\"></div>\n <div id=\"versions-modal\"></div>\n \n <script>\n // Update bulk actions button state\n function updateBulkActionsButton() {\n const checkboxes = document.querySelectorAll('input[type=\"checkbox\"].row-checkbox');\n const checkedCount = Array.from(checkboxes).filter(cb => cb.checked).length;\n const btn = document.getElementById('bulk-actions-btn');\n const menu = document.getElementById('bulk-actions-menu');\n\n if (!btn) return;\n\n if (checkedCount > 0) {\n btn.disabled = false;\n btn.className = 'inline-flex items-center gap-x-1.5 px-3 py-1.5 bg-white/90 dark:bg-zinc-800/90 backdrop-blur-sm text-zinc-950 dark:text-white text-sm font-medium rounded-full ring-1 ring-inset ring-cyan-200/50 dark:ring-cyan-700/50 hover:bg-gradient-to-r hover:from-cyan-50 hover:to-blue-50 dark:hover:from-cyan-900/30 dark:hover:to-blue-900/30 hover:ring-cyan-300 dark:hover:ring-cyan-600 transition-all duration-200';\n } else {\n btn.disabled = true;\n btn.className = 'inline-flex items-center gap-x-1.5 px-3 py-1.5 bg-zinc-100/60 dark:bg-zinc-800/60 backdrop-blur-sm text-zinc-400 dark:text-zinc-600 text-sm font-medium rounded-full ring-1 ring-inset ring-zinc-200/50 dark:ring-zinc-700/50 cursor-not-allowed';\n // Hide menu when no items selected\n if (menu) {\n menu.classList.remove('scale-100', 'opacity-100');\n menu.classList.add('scale-95', 'opacity-0', 'hidden');\n }\n }\n }\n\n // Select all functionality\n document.addEventListener('change', function(e) {\n if (e.target.id === 'select-all') {\n const checkboxes = document.querySelectorAll('.row-checkbox');\n checkboxes.forEach(cb => cb.checked = e.target.checked);\n updateBulkActionsButton();\n } else if (e.target.classList.contains('row-checkbox')) {\n updateBulkActionsButton();\n }\n });\n\n // Initialize button state on page load\n document.addEventListener('DOMContentLoaded', function() {\n updateBulkActionsButton();\n });\n\n // Toggle bulk actions dropdown\n function toggleBulkActionsDropdown() {\n const checkboxes = document.querySelectorAll('input[type=\"checkbox\"].row-checkbox');\n const checkedCount = Array.from(checkboxes).filter(cb => cb.checked).length;\n\n if (checkedCount === 0) return;\n\n const menu = document.getElementById('bulk-actions-menu');\n const isHidden = menu.classList.contains('hidden');\n\n if (isHidden) {\n menu.classList.remove('hidden');\n setTimeout(() => {\n menu.classList.remove('scale-95', 'opacity-0');\n menu.classList.add('scale-100', 'opacity-100');\n }, 10);\n } else {\n menu.classList.remove('scale-100', 'opacity-100');\n menu.classList.add('scale-95', 'opacity-0');\n setTimeout(() => {\n menu.classList.add('hidden');\n }, 100);\n }\n }\n\n // Close dropdown when clicking outside\n document.addEventListener('click', function(e) {\n const dropdown = document.getElementById('bulk-actions-dropdown');\n const menu = document.getElementById('bulk-actions-menu');\n if (dropdown && menu && !dropdown.contains(e.target)) {\n menu.classList.remove('scale-100', 'opacity-100');\n menu.classList.add('scale-95', 'opacity-0');\n setTimeout(() => {\n menu.classList.add('hidden');\n }, 100);\n }\n });\n\n // Store current bulk action context\n let currentBulkAction = null;\n let currentSelectedIds = [];\n\n // Perform bulk action\n function performBulkAction(action) {\n const selectedIds = Array.from(document.querySelectorAll('input[type=\"checkbox\"].row-checkbox:checked'))\n .map(cb => cb.value)\n .filter(id => id);\n\n if (selectedIds.length === 0) {\n alert('Please select at least one item');\n return;\n }\n\n // Store context for confirmation\n currentBulkAction = action;\n currentSelectedIds = selectedIds;\n\n // Update dialog content based on action\n updateDialogContent(action, selectedIds.length);\n\n // Show confirmation dialog\n showConfirmDialog('bulk-action-confirm');\n }\n\n // Update dialog content dynamically\n function updateDialogContent(action, count) {\n const dialog = document.getElementById('bulk-action-confirm');\n const titleEl = dialog.querySelector('h3');\n const messageEl = dialog.querySelector('p');\n const confirmBtn = dialog.querySelector('.confirm-button');\n\n let title, message, btnText, btnClass;\n\n switch(action) {\n case 'delete':\n title = 'Confirm Bulk Delete';\n message = 'Are you sure you want to delete ' + count + ' selected item' + (count > 1 ? 's' : '') + '? This action cannot be undone.';\n btnText = 'Delete';\n btnClass = 'bg-red-500 hover:bg-red-400';\n break;\n case 'publish':\n title = 'Confirm Bulk Publish';\n message = 'Are you sure you want to publish ' + count + ' selected item' + (count > 1 ? 's' : '') + '? They will become publicly visible.';\n btnText = 'Publish';\n btnClass = 'bg-green-500 hover:bg-green-400';\n break;\n case 'draft':\n title = 'Confirm Bulk Draft';\n message = 'Are you sure you want to move ' + count + ' selected item' + (count > 1 ? 's' : '') + ' to draft status? They will be unpublished.';\n btnText = 'Move to Draft';\n btnClass = 'bg-blue-500 hover:bg-blue-400';\n break;\n default:\n title = 'Confirm Bulk Action';\n message = 'Are you sure you want to perform this action on ' + count + ' selected item' + (count > 1 ? 's' : '') + '?';\n btnText = 'Confirm';\n btnClass = 'bg-blue-500 hover:bg-blue-400';\n }\n\n titleEl.textContent = title;\n messageEl.textContent = message;\n confirmBtn.textContent = btnText;\n confirmBtn.className = confirmBtn.className.replace(/bg-\\w+-\\d+\\s+hover:bg-\\w+-\\d+/, btnClass);\n }\n\n // Execute the bulk action after confirmation\n function executeBulkAction() {\n if (!currentBulkAction || currentSelectedIds.length === 0) return;\n\n // Close dropdown\n const menu = document.getElementById('bulk-actions-menu');\n menu.classList.add('hidden');\n\n fetch('/admin/content/bulk-action', {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json'\n },\n body: JSON.stringify({\n action: currentBulkAction,\n ids: currentSelectedIds\n })\n })\n .then(res => res.json())\n .then(data => {\n if (data.success) {\n location.reload();\n } else {\n alert('Error: ' + (data.error || 'Unknown error'));\n }\n })\n .catch(err => {\n console.error('Bulk action error:', err);\n alert('Failed to perform bulk action');\n })\n .finally(() => {\n // Clear context\n currentBulkAction = null;\n currentSelectedIds = [];\n });\n }\n\n // Helper to get action text for display\n function getActionText(action) {\n const actionCount = currentSelectedIds.length;\n switch(action) {\n case 'publish':\n return \\`publish \\${actionCount} item\\${actionCount > 1 ? 's' : ''}\\`;\n case 'draft':\n return \\`move \\${actionCount} item\\${actionCount > 1 ? 's' : ''} to draft\\`;\n case 'delete':\n return \\`delete \\${actionCount} item\\${actionCount > 1 ? 's' : ''}\\`;\n default:\n return \\`perform action on \\${actionCount} item\\${actionCount > 1 ? 's' : ''}\\`;\n }\n }\n\n </script>\n\n <!-- Confirmation Dialog for Bulk Actions -->\n ${renderConfirmationDialog({\n id: 'bulk-action-confirm',\n title: 'Confirm Bulk Action',\n message: 'Are you sure you want to perform this action? This operation will affect multiple items.',\n confirmText: 'Confirm',\n cancelText: 'Cancel',\n confirmClass: 'bg-blue-500 hover:bg-blue-400',\n iconColor: 'blue',\n onConfirm: 'executeBulkAction()'\n })}\n\n <!-- Confirmation Dialog Script -->\n ${getConfirmationDialogScript()}\n `\n\n // Prepare layout data\n const layoutData: AdminLayoutCatalystData = {\n title: 'Content Management',\n pageTitle: 'Content Management',\n currentPath: '/admin/content',\n user: data.user,\n version: data.version,\n content: pageContent\n }\n\n return renderAdminLayoutCatalyst(layoutData)\n}\n","export interface ContentVersion {\n id: string\n version: number\n data: any\n author_id: string\n author_name?: string\n created_at: number\n is_current?: boolean\n}\n\nexport interface VersionHistoryData {\n contentId: string\n versions: ContentVersion[]\n currentVersion: number\n}\n\nexport function renderVersionHistory(data: VersionHistoryData): string {\n return `\n <div class=\"version-history-modal\">\n <div class=\"backdrop-blur-xl bg-white/10 rounded-xl border border-white/20 shadow-2xl w-full max-w-4xl max-h-[90vh] overflow-hidden\">\n <!-- Header -->\n <div class=\"relative px-6 py-4 border-b border-white/10\">\n <div class=\"absolute inset-0 bg-gradient-to-r from-blue-600/10 via-purple-600/10 to-pink-600/10\"></div>\n <div class=\"relative flex items-center justify-between\">\n <h3 class=\"text-lg font-semibold text-white\">Version History</h3>\n <button onclick=\"closeVersionHistory()\" class=\"text-gray-300 hover:text-white\">\n <svg class=\"w-6 h-6\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M6 18L18 6M6 6l12 12\"></path>\n </svg>\n </button>\n </div>\n </div>\n \n <!-- Versions List -->\n <div class=\"overflow-y-auto max-h-[calc(90vh-120px)]\">\n <div class=\"p-6 space-y-4\">\n ${data.versions.map((version, index) => `\n <div class=\"version-item backdrop-blur-sm bg-white/5 rounded-xl border border-white/10 p-4 ${version.is_current ? 'ring-2 ring-blue-500/50' : ''}\">\n <div class=\"flex items-center justify-between mb-3\">\n <div class=\"flex items-center space-x-3\">\n <span class=\"inline-flex items-center px-3 py-1 rounded-full text-xs font-medium ${version.is_current ? 'bg-blue-500/20 text-blue-300' : 'bg-white/10 text-gray-300'}\">\n Version ${version.version}${version.is_current ? ' (Current)' : ''}\n </span>\n <span class=\"text-sm text-gray-300\">\n ${new Date(version.created_at).toLocaleString()}\n </span>\n </div>\n <div class=\"flex items-center space-x-2\">\n ${!version.is_current ? `\n <button \n onclick=\"restoreVersion('${data.contentId}', ${version.version})\"\n class=\"inline-flex items-center px-3 py-1 bg-green-600 text-white text-sm rounded-xl hover:bg-green-700 transition-all\"\n >\n <svg class=\"w-4 h-4 mr-1\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M3 10h10a8 8 0 018 8v2M3 10l6 6m-6-6l6-6\"></path>\n </svg>\n Restore\n </button>\n ` : ''}\n <button \n onclick=\"previewVersion('${data.contentId}', ${version.version})\"\n class=\"inline-flex items-center px-3 py-1 bg-blue-600 text-white text-sm rounded-xl hover:bg-blue-700 transition-all\"\n >\n <svg class=\"w-4 h-4 mr-1\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M15 12a3 3 0 11-6 0 3 3 0 016 0z\"></path>\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z\"></path>\n </svg>\n Preview\n </button>\n </div>\n </div>\n \n <!-- Version Summary -->\n <div class=\"version-summary text-sm\">\n <div class=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\n <div>\n <span class=\"text-gray-400\">Title:</span>\n <span class=\"text-white ml-2\">${escapeHtml(version.data?.title || 'Untitled')}</span>\n </div>\n <div>\n <span class=\"text-gray-400\">Author:</span>\n <span class=\"text-white ml-2\">${escapeHtml(version.author_name || 'Unknown')}</span>\n </div>\n ${version.data?.excerpt ? `\n <div class=\"md:col-span-2\">\n <span class=\"text-gray-400\">Excerpt:</span>\n <p class=\"text-white mt-1 text-xs\">${escapeHtml(version.data.excerpt.substring(0, 200))}${version.data.excerpt.length > 200 ? '...' : ''}</p>\n </div>\n ` : ''}\n </div>\n </div>\n \n <!-- Changes Summary (if not current) -->\n ${!version.is_current && index < data.versions.length - 1 ? `\n <div class=\"mt-3 pt-3 border-t border-white/10\">\n <button \n onclick=\"toggleChanges('changes-${version.version}')\"\n class=\"text-sm text-blue-400 hover:text-blue-300 transition-colors\"\n >\n <svg class=\"w-4 h-4 inline mr-1\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M8 9l4-4 4 4m0 6l-4 4-4-4\"></path>\n </svg>\n View Changes\n </button>\n <div id=\"changes-${version.version}\" class=\"hidden mt-2 text-xs text-gray-300\">\n <em>Change detection coming soon...</em>\n </div>\n </div>\n ` : ''}\n </div>\n `).join('')}\n </div>\n </div>\n \n <!-- Footer -->\n <div class=\"px-6 py-4 border-t border-white/10 bg-white/5\">\n <div class=\"flex justify-between items-center\">\n <span class=\"text-sm text-gray-400\">\n ${data.versions.length} version${data.versions.length !== 1 ? 's' : ''} total\n </span>\n <button \n onclick=\"closeVersionHistory()\"\n class=\"px-4 py-2 bg-white/10 text-white rounded-xl border border-white/20 hover:bg-white/20 transition-all\"\n >\n Close\n </button>\n </div>\n </div>\n </div>\n </div>\n \n <script>\n function closeVersionHistory() {\n document.querySelector('.version-history-modal').closest('.fixed').remove();\n }\n \n function restoreVersion(contentId, version) {\n if (confirm(\\`Are you sure you want to restore to version \\${version}? This will create a new version with the restored content.\\`)) {\n fetch(\\`/admin/content/\\${contentId}/restore/\\${version}\\`, {\n method: 'POST'\n })\n .then(response => response.json())\n .then(data => {\n if (data.success) {\n showNotification('Version restored successfully! Refreshing page...', 'success');\n setTimeout(() => {\n window.location.reload();\n }, 1500);\n } else {\n showNotification('Failed to restore version', 'error');\n }\n })\n .catch(error => {\n console.error('Error restoring version:', error);\n showNotification('Error restoring version', 'error');\n });\n }\n }\n \n function previewVersion(contentId, version) {\n const preview = window.open('', '_blank');\n preview.document.write('<p>Loading version preview...</p>');\n \n fetch(\\`/admin/content/\\${contentId}/version/\\${version}/preview\\`)\n .then(response => response.text())\n .then(html => {\n preview.document.open();\n preview.document.write(html);\n preview.document.close();\n })\n .catch(error => {\n preview.document.write('<p>Error loading preview</p>');\n });\n }\n \n function toggleChanges(elementId) {\n const element = document.getElementById(elementId);\n element.classList.toggle('hidden');\n }\n </script>\n `\n}\n\nfunction escapeHtml(text: string): string {\n if (typeof text !== 'string') return String(text || '')\n return text.replace(/[&<>\"']/g, (char) => ({\n '&': '&',\n '<': '<',\n '>': '>',\n '\"': '"',\n \"'\": '''\n }[char] || char))\n}","/**\n * Plugin Middleware\n *\n * Provides middleware functions for checking plugin status and enforcing plugin requirements\n */\n\nimport type { D1Database } from '@cloudflare/workers-types'\n\n/**\n * Check if a plugin is active\n * @param db - The D1 database instance\n * @param pluginId - The plugin ID to check\n * @returns Promise<boolean> - True if the plugin is active, false otherwise\n */\nexport async function isPluginActive(db: D1Database, pluginId: string): Promise<boolean> {\n try {\n const result = await db\n .prepare('SELECT status FROM plugins WHERE id = ?')\n .bind(pluginId)\n .first()\n\n return result?.status === 'active'\n } catch (error) {\n console.error(`[isPluginActive] Error checking plugin status for ${pluginId}:`, error)\n return false\n }\n}\n\n/**\n * Middleware to require a plugin to be active\n * Throws an error if the plugin is not active\n * @param db - The D1 database instance\n * @param pluginId - The plugin ID to check\n * @throws Error if plugin is not active\n */\nexport async function requireActivePlugin(db: D1Database, pluginId: string): Promise<void> {\n const isActive = await isPluginActive(db, pluginId)\n if (!isActive) {\n throw new Error(`Plugin '${pluginId}' is required but is not active`)\n }\n}\n\n/**\n * Middleware to require multiple plugins to be active\n * Throws an error if any plugin is not active\n * @param db - The D1 database instance\n * @param pluginIds - Array of plugin IDs to check\n * @throws Error if any plugin is not active\n */\nexport async function requireActivePlugins(db: D1Database, pluginIds: string[]): Promise<void> {\n for (const pluginId of pluginIds) {\n await requireActivePlugin(db, pluginId)\n }\n}\n\n/**\n * Get all active plugins\n * @param db - The D1 database instance\n * @returns Promise<any[]> - Array of active plugin records\n */\nexport async function getActivePlugins(db: D1Database): Promise<any[]> {\n try {\n const { results } = await db\n .prepare('SELECT * FROM plugins WHERE status = ?')\n .bind('active')\n .all()\n\n return results || []\n } catch (error) {\n console.error('[getActivePlugins] Error fetching active plugins:', error)\n return []\n }\n}\n","import { Hono } from 'hono'\nimport { html } from 'hono/html'\nimport type { D1Database, KVNamespace } from '@cloudflare/workers-types'\nimport { requireAuth } from '../middleware'\nimport { renderContentFormPage, ContentFormData } from '../templates/pages/admin-content-form.template'\nimport { renderContentListPage, ContentListPageData } from '../templates/pages/admin-content-list.template'\nimport { renderVersionHistory, VersionHistoryData, ContentVersion } from '../templates/components/version-history.template'\nimport { isPluginActive } from '../middleware/plugin-middleware'\nimport { getCacheService, CACHE_CONFIGS } from '../services/cache'\nimport type { Bindings, Variables } from '../app'\nimport { PluginService } from '../services/plugin-service'\n\nconst adminContentRoutes = new Hono<{ Bindings: Bindings; Variables: Variables }>()\n\n// Apply authentication middleware\nadminContentRoutes.use('*', requireAuth())\n\n// Get collection fields\nasync function getCollectionFields(db: D1Database, collectionId: string) {\n const cache = getCacheService(CACHE_CONFIGS.collection!)\n\n return cache.getOrSet(\n cache.generateKey('fields', collectionId),\n async () => {\n // First, check if collection has a schema (code-based collection)\n const collectionStmt = db.prepare('SELECT schema FROM collections WHERE id = ?')\n const collectionRow = await collectionStmt.bind(collectionId).first() as any\n\n if (collectionRow && collectionRow.schema) {\n try {\n const schema = typeof collectionRow.schema === 'string' ? JSON.parse(collectionRow.schema) : collectionRow.schema\n if (schema && schema.properties) {\n // Convert schema properties to field format\n let fieldOrder = 0\n return Object.entries(schema.properties).map(([fieldName, fieldConfig]: [string, any]) => {\n // For select fields, convert enum/enumLabels to options array\n let fieldOptions = { ...fieldConfig }\n if (fieldConfig.type === 'select' && fieldConfig.enum) {\n fieldOptions.options = fieldConfig.enum.map((value: string, index: number) => ({\n value: value,\n label: fieldConfig.enumLabels?.[index] || value\n }))\n }\n\n return {\n id: `schema-${fieldName}`,\n field_name: fieldName,\n field_type: fieldConfig.type || 'string',\n field_label: fieldConfig.title || fieldName,\n field_options: fieldOptions,\n field_order: fieldOrder++,\n is_required: fieldConfig.required === true || (schema.required && schema.required.includes(fieldName)),\n is_searchable: false\n }\n })\n }\n } catch (e) {\n console.error('Error parsing collection schema:', e)\n }\n }\n\n // Fall back to content_fields table for legacy collections\n const stmt = db.prepare(`\n SELECT * FROM content_fields\n WHERE collection_id = ?\n ORDER BY field_order ASC\n `)\n const { results } = await stmt.bind(collectionId).all()\n\n return (results || []).map((row: any) => ({\n id: row.id,\n field_name: row.field_name,\n field_type: row.field_type,\n field_label: row.field_label,\n field_options: row.field_options ? JSON.parse(row.field_options) : {},\n field_order: row.field_order,\n is_required: row.is_required === 1,\n is_searchable: row.is_searchable === 1\n }))\n }\n )\n}\n\n// Get collection by ID\nasync function getCollection(db: D1Database, collectionId: string) {\n const cache = getCacheService(CACHE_CONFIGS.collection!)\n\n return cache.getOrSet(\n cache.generateKey('collection', collectionId),\n async () => {\n const stmt = db.prepare('SELECT * FROM collections WHERE id = ? AND is_active = 1')\n const collection = await stmt.bind(collectionId).first() as any\n\n if (!collection) return null\n\n return {\n id: collection.id,\n name: collection.name,\n display_name: collection.display_name,\n description: collection.description,\n schema: collection.schema ? JSON.parse(collection.schema) : {}\n }\n }\n )\n}\n\n// Content list (main page)\nadminContentRoutes.get('/', async (c) => {\n try {\n const user = c.get('user')\n const url = new URL(c.req.url)\n const db = c.env.DB\n \n // Get query parameters\n const page = parseInt(url.searchParams.get('page') || '1')\n const limit = parseInt(url.searchParams.get('limit') || '20')\n const modelName = url.searchParams.get('model') || 'all'\n const status = url.searchParams.get('status') || 'all'\n const search = url.searchParams.get('search') || ''\n const offset = (page - 1) * limit\n \n // Get all collections for filter dropdown\n const collectionsStmt = db.prepare('SELECT id, name, display_name FROM collections WHERE is_active = 1 ORDER BY display_name')\n const { results: collectionsResults } = await collectionsStmt.all()\n const models = (collectionsResults || []).map((row: any) => ({\n name: row.name,\n displayName: row.display_name\n }))\n \n // Build where conditions\n const conditions: string[] = []\n const params: any[] = []\n\n // Always filter out deleted content unless specifically requested\n if (status !== 'deleted') {\n conditions.push(\"c.status != 'deleted'\")\n }\n\n if (search) {\n conditions.push('(c.title LIKE ? OR c.slug LIKE ?)')\n params.push(`%${search}%`, `%${search}%`)\n }\n\n if (modelName !== 'all') {\n conditions.push('col.name = ?')\n params.push(modelName)\n }\n\n if (status !== 'all' && status !== 'deleted') {\n conditions.push('c.status = ?')\n params.push(status)\n } else if (status === 'deleted') {\n conditions.push(\"c.status = 'deleted'\")\n }\n\n const whereClause = conditions.length > 0 ? `WHERE ${conditions.join(' AND ')}` : ''\n \n // Get total count\n const countStmt = db.prepare(`\n SELECT COUNT(*) as count \n FROM content c\n JOIN collections col ON c.collection_id = col.id\n ${whereClause}\n `)\n const countResult = await countStmt.bind(...params).first() as any\n const totalItems = countResult?.count || 0\n \n // Get content items\n const contentStmt = db.prepare(`\n SELECT c.id, c.title, c.slug, c.status, c.created_at, c.updated_at,\n col.name as collection_name, col.display_name as collection_display_name,\n u.first_name, u.last_name, u.email as author_email\n FROM content c\n JOIN collections col ON c.collection_id = col.id\n LEFT JOIN users u ON c.author_id = u.id\n ${whereClause}\n ORDER BY c.updated_at DESC\n LIMIT ? OFFSET ?\n `)\n const { results } = await contentStmt.bind(...params, limit, offset).all()\n \n // Process content items\n const contentItems = (results || []).map((row: any) => {\n const statusConfig: Record<string, { class: string; text: string }> = {\n draft: {\n class: 'bg-zinc-50 dark:bg-zinc-500/10 text-zinc-700 dark:text-zinc-400 ring-1 ring-inset ring-zinc-600/20 dark:ring-zinc-500/20',\n text: 'Draft'\n },\n review: {\n class: 'bg-amber-50 dark:bg-amber-500/10 text-amber-700 dark:text-amber-400 ring-1 ring-inset ring-amber-600/20 dark:ring-amber-500/20',\n text: 'Under Review'\n },\n scheduled: {\n class: 'bg-blue-50 dark:bg-blue-500/10 text-blue-700 dark:text-blue-400 ring-1 ring-inset ring-blue-600/20 dark:ring-blue-500/20',\n text: 'Scheduled'\n },\n published: {\n class: 'bg-green-50 dark:bg-green-500/10 text-green-700 dark:text-green-400 ring-1 ring-inset ring-green-600/20 dark:ring-green-500/20',\n text: 'Published'\n },\n archived: {\n class: 'bg-purple-50 dark:bg-purple-500/10 text-purple-700 dark:text-purple-400 ring-1 ring-inset ring-purple-600/20 dark:ring-purple-500/20',\n text: 'Archived'\n },\n deleted: {\n class: 'bg-red-50 dark:bg-red-500/10 text-red-700 dark:text-red-400 ring-1 ring-inset ring-red-600/20 dark:ring-red-500/20',\n text: 'Deleted'\n }\n }\n\n const config = statusConfig[row.status as keyof typeof statusConfig] || statusConfig.draft\n const statusBadge = `\n <span class=\"inline-flex items-center rounded-md px-2 py-1 text-xs font-medium ${config?.class || ''}\">\n ${config?.text || row.status}\n </span>\n `\n \n const authorName = row.first_name && row.last_name \n ? `${row.first_name} ${row.last_name}`\n : row.author_email || 'Unknown'\n \n const formattedDate = new Date(row.updated_at).toLocaleDateString()\n \n // Determine available workflow actions based on status\n const availableActions: string[] = []\n switch (row.status) {\n case 'draft':\n availableActions.push('submit_for_review', 'publish')\n break\n case 'review':\n availableActions.push('approve', 'request_changes')\n break\n case 'published':\n availableActions.push('unpublish', 'archive')\n break\n case 'scheduled':\n availableActions.push('unschedule')\n break\n }\n \n return {\n id: row.id,\n title: row.title,\n slug: row.slug,\n modelName: row.collection_display_name,\n statusBadge,\n authorName,\n formattedDate,\n availableActions\n }\n })\n \n const pageData: ContentListPageData = {\n modelName,\n status,\n page,\n search,\n models,\n contentItems,\n totalItems,\n itemsPerPage: limit,\n user: user ? {\n name: user.email,\n email: user.email,\n role: user.role\n } : undefined,\n version: c.get('appVersion')\n }\n\n return c.html(renderContentListPage(pageData))\n } catch (error) {\n console.error('Error fetching content list:', error)\n return c.html(`<p>Error loading content: ${error}</p>`)\n }\n})\n\n// New content form\nadminContentRoutes.get('/new', async (c) => {\n try {\n const user = c.get('user')\n const url = new URL(c.req.url)\n const collectionId = url.searchParams.get('collection')\n \n if (!collectionId) {\n // Show collection selection page\n const db = c.env.DB\n const collectionsStmt = db.prepare('SELECT id, name, display_name, description FROM collections WHERE is_active = 1 ORDER BY display_name')\n const { results } = await collectionsStmt.all()\n \n const collections = (results || []).map((row: any) => ({\n id: row.id,\n name: row.name,\n display_name: row.display_name,\n description: row.description\n }))\n \n // Render collection selection page\n const selectionHTML = `\n <!DOCTYPE html>\n <html>\n <head>\n <title>Select Collection - SonicJS AI Admin</title>\n <script src=\"https://cdn.tailwindcss.com\"></script>\n </head>\n <body class=\"bg-gray-900 text-white\">\n <div class=\"min-h-screen flex items-center justify-center\">\n <div class=\"max-w-2xl w-full mx-auto p-8\">\n <h1 class=\"text-3xl font-bold mb-8 text-center\">Create New Content</h1>\n <p class=\"text-gray-300 text-center mb-8\">Select a collection to create content in:</p>\n \n <div class=\"grid gap-4\">\n ${collections.map(collection => `\n <a href=\"/admin/content/new?collection=${collection.id}\" \n class=\"block p-6 bg-gray-800 rounded-lg hover:bg-gray-700 transition-colors border border-gray-700\">\n <h3 class=\"text-xl font-semibold mb-2\">${collection.display_name}</h3>\n <p class=\"text-gray-400\">${collection.description || 'No description'}</p>\n </a>\n `).join('')}\n </div>\n \n <div class=\"mt-8 text-center\">\n <a href=\"/admin/content\" class=\"text-blue-400 hover:text-blue-300\">← Back to Content List</a>\n </div>\n </div>\n </div>\n </body>\n </html>\n `\n \n return c.html(selectionHTML)\n }\n \n const db = c.env.DB\n const collection = await getCollection(db, collectionId)\n \n if (!collection) {\n const formData: ContentFormData = {\n collection: { id: '', name: '', display_name: 'Unknown', schema: {} },\n fields: [],\n error: 'Collection not found.',\n user: user ? {\n name: user.email,\n email: user.email,\n role: user.role\n } : undefined\n }\n return c.html(renderContentFormPage(formData))\n }\n \n const fields = await getCollectionFields(db, collectionId)\n\n // Check if workflow plugin is active\n const workflowEnabled = await isPluginActive(db, 'workflow')\n\n // Check if TinyMCE plugin is active and get settings\n const tinymceEnabled = await isPluginActive(db, 'tinymce-plugin')\n let tinymceSettings\n if (tinymceEnabled) {\n const pluginService = new PluginService(db)\n const tinymcePlugin = await pluginService.getPlugin('tinymce-plugin')\n tinymceSettings = tinymcePlugin?.settings\n }\n\n // Check if Quill plugin is active and get settings\n const quillEnabled = await isPluginActive(db, 'quill-editor')\n let quillSettings\n if (quillEnabled) {\n const pluginService = new PluginService(db)\n const quillPlugin = await pluginService.getPlugin('quill-editor')\n quillSettings = quillPlugin?.settings\n }\n\n // Check if MDXEditor plugin is active and get settings\n const mdxeditorEnabled = await isPluginActive(db, 'easy-mdx')\n let mdxeditorSettings\n if (mdxeditorEnabled) {\n const pluginService = new PluginService(db)\n const mdxeditorPlugin = await pluginService.getPlugin('easy-mdx')\n mdxeditorSettings = mdxeditorPlugin?.settings\n }\n\n console.log('[Content Form /new] Editor plugins status:', {\n tinymce: tinymceEnabled,\n quill: quillEnabled,\n mdxeditor: mdxeditorEnabled,\n mdxeditorSettings\n })\n\n const formData: ContentFormData = {\n collection,\n fields,\n isEdit: false,\n workflowEnabled,\n tinymceEnabled,\n tinymceSettings,\n quillEnabled,\n quillSettings,\n mdxeditorEnabled,\n mdxeditorSettings,\n user: user ? {\n name: user.email,\n email: user.email,\n role: user.role\n } : undefined\n }\n \n return c.html(renderContentFormPage(formData))\n } catch (error) {\n console.error('Error loading new content form:', error)\n const formData: ContentFormData = {\n collection: { id: '', name: '', display_name: 'Unknown', schema: {} },\n fields: [],\n error: 'Failed to load content form.',\n user: c.get('user') ? {\n name: c.get('user')!.email,\n email: c.get('user')!.email,\n role: c.get('user')!.role\n } : undefined\n }\n return c.html(renderContentFormPage(formData))\n }\n})\n\n// Edit content form\nadminContentRoutes.get('/:id/edit', async (c) => {\n try {\n const id = c.req.param('id')\n const user = c.get('user')\n const db = c.env.DB\n const url = new URL(c.req.url)\n\n // Capture referrer parameters to preserve filters when returning to list\n const referrerParams = url.searchParams.get('ref') || ''\n\n // Get content with caching\n const cache = getCacheService(CACHE_CONFIGS.content!)\n const content = await cache.getOrSet(\n cache.generateKey('content', id),\n async () => {\n const contentStmt = db.prepare(`\n SELECT c.*, col.id as collection_id, col.name as collection_name,\n col.display_name as collection_display_name, col.description as collection_description,\n col.schema as collection_schema\n FROM content c\n JOIN collections col ON c.collection_id = col.id\n WHERE c.id = ?\n `)\n return await contentStmt.bind(id).first() as any\n }\n )\n\n if (!content) {\n const formData: ContentFormData = {\n collection: { id: '', name: '', display_name: 'Unknown', schema: {} },\n fields: [],\n error: 'Content not found.',\n user: user ? {\n name: user.email,\n email: user.email,\n role: user.role\n } : undefined\n }\n return c.html(renderContentFormPage(formData))\n }\n \n const collection = {\n id: content.collection_id,\n name: content.collection_name,\n display_name: content.collection_display_name,\n description: content.collection_description,\n schema: content.collection_schema ? JSON.parse(content.collection_schema) : {}\n }\n \n const fields = await getCollectionFields(db, content.collection_id)\n const contentData = content.data ? JSON.parse(content.data) : {}\n\n // Check if workflow plugin is active\n const workflowEnabled = await isPluginActive(db, 'workflow')\n\n // Check if TinyMCE plugin is active and get settings\n const tinymceEnabled = await isPluginActive(db, 'tinymce-plugin')\n let tinymceSettings\n if (tinymceEnabled) {\n const pluginService = new PluginService(db)\n const tinymcePlugin = await pluginService.getPlugin('tinymce-plugin')\n tinymceSettings = tinymcePlugin?.settings\n }\n\n // Check if Quill plugin is active and get settings\n const quillEnabled = await isPluginActive(db, 'quill-editor')\n let quillSettings\n if (quillEnabled) {\n const pluginService = new PluginService(db)\n const quillPlugin = await pluginService.getPlugin('quill-editor')\n quillSettings = quillPlugin?.settings\n }\n\n // Check if MDXEditor plugin is active and get settings\n const mdxeditorEnabled = await isPluginActive(db, 'easy-mdx')\n let mdxeditorSettings\n if (mdxeditorEnabled) {\n const pluginService = new PluginService(db)\n const mdxeditorPlugin = await pluginService.getPlugin('easy-mdx')\n mdxeditorSettings = mdxeditorPlugin?.settings\n }\n\n const formData: ContentFormData = {\n id: content.id,\n title: content.title,\n slug: content.slug,\n data: contentData,\n status: content.status,\n scheduled_publish_at: content.scheduled_publish_at,\n scheduled_unpublish_at: content.scheduled_unpublish_at,\n review_status: content.review_status,\n meta_title: content.meta_title,\n meta_description: content.meta_description,\n collection,\n fields,\n isEdit: true,\n workflowEnabled,\n tinymceEnabled,\n tinymceSettings,\n quillEnabled,\n quillSettings,\n mdxeditorEnabled,\n mdxeditorSettings,\n referrerParams,\n user: user ? {\n name: user.email,\n email: user.email,\n role: user.role\n } : undefined,\n version: c.get('appVersion')\n }\n\n return c.html(renderContentFormPage(formData))\n } catch (error) {\n console.error('Error loading edit content form:', error)\n const formData: ContentFormData = {\n collection: { id: '', name: '', display_name: 'Unknown', schema: {} },\n fields: [],\n error: 'Failed to load content for editing.',\n user: c.get('user') ? {\n name: c.get('user')!.email,\n email: c.get('user')!.email,\n role: c.get('user')!.role\n } : undefined\n }\n return c.html(renderContentFormPage(formData))\n }\n})\n\n// Create content\nadminContentRoutes.post('/', async (c) => {\n try {\n const user = c.get('user')\n const formData = await c.req.formData()\n const collectionId = formData.get('collection_id') as string\n const action = formData.get('action') as string\n \n if (!collectionId) {\n return c.html(html`\n <div class=\"bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded\">\n Collection ID is required.\n </div>\n `)\n }\n \n const db = c.env.DB\n const collection = await getCollection(db, collectionId)\n \n if (!collection) {\n return c.html(html`\n <div class=\"bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded\">\n Collection not found.\n </div>\n `)\n }\n \n const fields = await getCollectionFields(db, collectionId)\n \n // Extract field data\n const data: any = {}\n const errors: Record<string, string[]> = {}\n \n for (const field of fields) {\n const value = formData.get(field.field_name)\n\n // Validation\n if (field.is_required && (!value || value.toString().trim() === '')) {\n errors[field.field_name] = [`${field.field_label} is required`]\n continue\n }\n\n // Type conversion and validation\n switch (field.field_type) {\n case 'number':\n if (value && isNaN(Number(value))) {\n errors[field.field_name] = [`${field.field_label} must be a valid number`]\n } else {\n data[field.field_name] = value ? Number(value) : null\n }\n break\n case 'boolean':\n data[field.field_name] = formData.get(`${field.field_name}_submitted`) ? (value === 'true') : false\n break\n case 'select':\n if (field.field_options?.multiple) {\n data[field.field_name] = formData.getAll(`${field.field_name}[]`)\n } else {\n data[field.field_name] = value\n }\n break\n default:\n data[field.field_name] = value\n }\n }\n \n // Check for validation errors\n if (Object.keys(errors).length > 0) {\n const formDataWithErrors: ContentFormData = {\n collection,\n fields,\n data,\n validationErrors: errors,\n error: 'Please fix the validation errors below.',\n user: user ? {\n name: user.email,\n email: user.email,\n role: user.role\n } : undefined\n }\n return c.html(renderContentFormPage(formDataWithErrors))\n }\n \n // Generate slug if not provided\n let slug = data.slug || data.title\n if (slug) {\n slug = slug.toLowerCase()\n .replace(/[^a-z0-9\\s-]/g, '')\n .replace(/\\s+/g, '-')\n .replace(/-+/g, '-')\n .trim('-')\n }\n \n // Determine status\n let status = formData.get('status') as string || 'draft'\n if (action === 'save_and_publish') {\n status = 'published'\n }\n \n // Handle scheduling\n const scheduledPublishAt = formData.get('scheduled_publish_at') as string\n const scheduledUnpublishAt = formData.get('scheduled_unpublish_at') as string\n \n // Create content\n const contentId = crypto.randomUUID()\n const now = Date.now()\n \n const insertStmt = db.prepare(`\n INSERT INTO content (\n id, collection_id, slug, title, data, status,\n scheduled_publish_at, scheduled_unpublish_at,\n meta_title, meta_description, author_id, created_by, created_at, updated_at\n )\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n `)\n\n await insertStmt.bind(\n contentId,\n collectionId,\n slug,\n data.title || 'Untitled',\n JSON.stringify(data),\n status,\n scheduledPublishAt ? new Date(scheduledPublishAt).getTime() : null,\n scheduledUnpublishAt ? new Date(scheduledUnpublishAt).getTime() : null,\n data.meta_title || null,\n data.meta_description || null,\n user?.userId || 'unknown',\n user?.userId || 'unknown',\n now,\n now\n ).run()\n\n // Invalidate collection content list cache\n const cache = getCacheService(CACHE_CONFIGS.content!)\n await cache.invalidate(`content:list:${collectionId}:*`)\n\n // Create initial version\n const versionStmt = db.prepare(`\n INSERT INTO content_versions (id, content_id, version, data, author_id, created_at)\n VALUES (?, ?, ?, ?, ?, ?)\n `)\n \n await versionStmt.bind(\n crypto.randomUUID(),\n contentId,\n 1,\n JSON.stringify(data),\n user?.userId || 'unknown',\n now\n ).run()\n \n // Log workflow action\n const workflowStmt = db.prepare(`\n INSERT INTO workflow_history (id, content_id, action, from_status, to_status, user_id, created_at)\n VALUES (?, ?, ?, ?, ?, ?, ?)\n `)\n \n await workflowStmt.bind(\n crypto.randomUUID(),\n contentId,\n 'created',\n 'none',\n status,\n user?.userId || 'unknown',\n now\n ).run()\n \n // Handle different actions\n const referrerParams = formData.get('referrer_params') as string\n const redirectUrl = action === 'save_and_continue'\n ? `/admin/content/${contentId}/edit?success=Content saved successfully!${referrerParams ? `&ref=${encodeURIComponent(referrerParams)}` : ''}`\n : referrerParams\n ? `/admin/content?${referrerParams}&success=Content created successfully!`\n : `/admin/content?collection=${collectionId}&success=Content created successfully!`\n\n // Check if this is an HTMX request\n const isHTMX = c.req.header('HX-Request') === 'true'\n \n if (isHTMX) {\n // For HTMX requests, use HX-Redirect header to trigger client-side redirect\n return c.text('', 200, {\n 'HX-Redirect': redirectUrl\n })\n } else {\n // For regular requests, use server-side redirect\n return c.redirect(redirectUrl)\n }\n \n } catch (error) {\n console.error('Error creating content:', error)\n return c.html(html`\n <div class=\"bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded\">\n Failed to create content. Please try again.\n </div>\n `)\n }\n})\n\n// Update content\nadminContentRoutes.put('/:id', async (c) => {\n try {\n const id = c.req.param('id')\n const user = c.get('user')\n const formData = await c.req.formData()\n const action = formData.get('action') as string\n \n const db = c.env.DB\n \n // Get existing content\n const contentStmt = db.prepare('SELECT * FROM content WHERE id = ?')\n const existingContent = await contentStmt.bind(id).first() as any\n \n if (!existingContent) {\n return c.html(html`\n <div class=\"bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded\">\n Content not found.\n </div>\n `)\n }\n \n const collection = await getCollection(db, existingContent.collection_id)\n if (!collection) {\n return c.html(html`\n <div class=\"bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded\">\n Collection not found.\n </div>\n `)\n }\n \n const fields = await getCollectionFields(db, existingContent.collection_id)\n \n // Extract and validate field data (same as create)\n const data: any = {}\n const errors: Record<string, string[]> = {}\n \n for (const field of fields) {\n const value = formData.get(field.field_name)\n \n if (field.is_required && (!value || value.toString().trim() === '')) {\n errors[field.field_name] = [`${field.field_label} is required`]\n continue\n }\n \n switch (field.field_type) {\n case 'number':\n if (value && isNaN(Number(value))) {\n errors[field.field_name] = [`${field.field_label} must be a valid number`]\n } else {\n data[field.field_name] = value ? Number(value) : null\n }\n break\n case 'boolean':\n data[field.field_name] = formData.get(`${field.field_name}_submitted`) ? (value === 'true') : false\n break\n case 'select':\n if (field.field_options?.multiple) {\n data[field.field_name] = formData.getAll(`${field.field_name}[]`)\n } else {\n data[field.field_name] = value\n }\n break\n default:\n data[field.field_name] = value\n }\n }\n \n if (Object.keys(errors).length > 0) {\n const formDataWithErrors: ContentFormData = {\n id,\n collection,\n fields,\n data,\n validationErrors: errors,\n error: 'Please fix the validation errors below.',\n isEdit: true,\n user: user ? {\n name: user.email,\n email: user.email,\n role: user.role\n } : undefined\n }\n return c.html(renderContentFormPage(formDataWithErrors))\n }\n \n // Update slug if title changed\n let slug = data.slug || data.title\n if (slug) {\n slug = slug.toLowerCase()\n .replace(/[^a-z0-9\\s-]/g, '')\n .replace(/\\s+/g, '-')\n .replace(/-+/g, '-')\n .trim('-')\n }\n \n // Determine status\n let status = formData.get('status') as string || existingContent.status\n if (action === 'save_and_publish') {\n status = 'published'\n }\n \n // Handle scheduling\n const scheduledPublishAt = formData.get('scheduled_publish_at') as string\n const scheduledUnpublishAt = formData.get('scheduled_unpublish_at') as string\n \n // Update content\n const now = Date.now()\n \n const updateStmt = db.prepare(`\n UPDATE content SET\n slug = ?, title = ?, data = ?, status = ?,\n scheduled_publish_at = ?, scheduled_unpublish_at = ?,\n meta_title = ?, meta_description = ?, updated_at = ?\n WHERE id = ?\n `)\n \n await updateStmt.bind(\n slug,\n data.title || 'Untitled',\n JSON.stringify(data),\n status,\n scheduledPublishAt ? new Date(scheduledPublishAt).getTime() : null,\n scheduledUnpublishAt ? new Date(scheduledUnpublishAt).getTime() : null,\n data.meta_title || null,\n data.meta_description || null,\n now,\n id\n ).run()\n\n // Invalidate content cache\n const cache = getCacheService(CACHE_CONFIGS.content!)\n await cache.delete(cache.generateKey('content', id))\n await cache.invalidate(`content:list:${existingContent.collection_id}:*`)\n\n // Create new version if content changed\n const existingData = JSON.parse(existingContent.data || '{}')\n if (JSON.stringify(existingData) !== JSON.stringify(data)) {\n // Get next version number\n const versionCountStmt = db.prepare('SELECT MAX(version) as max_version FROM content_versions WHERE content_id = ?')\n const versionResult = await versionCountStmt.bind(id).first() as any\n const nextVersion = (versionResult?.max_version || 0) + 1\n \n const versionStmt = db.prepare(`\n INSERT INTO content_versions (id, content_id, version, data, author_id, created_at)\n VALUES (?, ?, ?, ?, ?, ?)\n `)\n \n await versionStmt.bind(\n crypto.randomUUID(),\n id,\n nextVersion,\n JSON.stringify(data),\n user?.userId || 'unknown',\n now\n ).run()\n }\n \n // Log workflow action if status changed\n if (status !== existingContent.status) {\n const workflowStmt = db.prepare(`\n INSERT INTO workflow_history (id, content_id, action, from_status, to_status, user_id, created_at)\n VALUES (?, ?, ?, ?, ?, ?, ?)\n `)\n \n await workflowStmt.bind(\n crypto.randomUUID(),\n id,\n 'status_changed',\n existingContent.status,\n status,\n user?.userId || 'unknown',\n now\n ).run()\n }\n \n // Handle different actions\n const referrerParams = formData.get('referrer_params') as string\n const redirectUrl = action === 'save_and_continue'\n ? `/admin/content/${id}/edit?success=Content updated successfully!${referrerParams ? `&ref=${encodeURIComponent(referrerParams)}` : ''}`\n : referrerParams\n ? `/admin/content?${referrerParams}&success=Content updated successfully!`\n : `/admin/content?collection=${existingContent.collection_id}&success=Content updated successfully!`\n\n // Check if this is an HTMX request\n const isHTMX = c.req.header('HX-Request') === 'true'\n \n if (isHTMX) {\n // For HTMX requests, use HX-Redirect header to trigger client-side redirect\n return c.text('', 200, {\n 'HX-Redirect': redirectUrl\n })\n } else {\n // For regular requests, use server-side redirect\n return c.redirect(redirectUrl)\n }\n \n } catch (error) {\n console.error('Error updating content:', error)\n return c.html(html`\n <div class=\"bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded\">\n Failed to update content. Please try again.\n </div>\n `)\n }\n})\n\n// Content preview\nadminContentRoutes.post('/preview', async (c) => {\n try {\n const formData = await c.req.formData()\n const collectionId = formData.get('collection_id') as string\n \n const db = c.env.DB\n const collection = await getCollection(db, collectionId)\n \n if (!collection) {\n return c.html('<p>Collection not found</p>')\n }\n \n const fields = await getCollectionFields(db, collectionId)\n \n // Extract field data for preview\n const data: any = {}\n for (const field of fields) {\n const value = formData.get(field.field_name)\n \n switch (field.field_type) {\n case 'number':\n data[field.field_name] = value ? Number(value) : null\n break\n case 'boolean':\n data[field.field_name] = value === 'true'\n break\n case 'select':\n if (field.field_options?.multiple) {\n data[field.field_name] = formData.getAll(`${field.field_name}[]`)\n } else {\n data[field.field_name] = value\n }\n break\n default:\n data[field.field_name] = value\n }\n }\n \n // Generate preview HTML\n const previewHTML = `\n <!DOCTYPE html>\n <html lang=\"en\">\n <head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <title>Preview: ${data.title || 'Untitled'}</title>\n <style>\n body { font-family: Arial, sans-serif; max-width: 800px; margin: 0 auto; padding: 20px; }\n h1 { color: #333; }\n .meta { color: #666; font-size: 14px; margin-bottom: 20px; }\n .content { line-height: 1.6; }\n </style>\n </head>\n <body>\n <h1>${data.title || 'Untitled'}</h1>\n <div class=\"meta\">\n <strong>Collection:</strong> ${collection.display_name}<br>\n <strong>Status:</strong> ${formData.get('status') || 'draft'}<br>\n ${data.meta_description ? `<strong>Description:</strong> ${data.meta_description}<br>` : ''}\n </div>\n <div class=\"content\">\n ${data.content || '<p>No content provided.</p>'}\n </div>\n \n <h3>All Fields:</h3>\n <table border=\"1\" style=\"border-collapse: collapse; width: 100%;\">\n <tr><th>Field</th><th>Value</th></tr>\n ${fields.map(field => `\n <tr>\n <td><strong>${field.field_label}</strong></td>\n <td>${data[field.field_name] || '<em>empty</em>'}</td>\n </tr>\n `).join('')}\n </table>\n </body>\n </html>\n `\n \n return c.html(previewHTML)\n } catch (error) {\n console.error('Error generating preview:', error)\n return c.html('<p>Error generating preview</p>')\n }\n})\n\n// Duplicate content\nadminContentRoutes.post('/duplicate', async (c) => {\n try {\n const user = c.get('user')\n const formData = await c.req.formData()\n const originalId = formData.get('id') as string\n \n if (!originalId) {\n return c.json({ success: false, error: 'Content ID required' })\n }\n \n const db = c.env.DB\n \n // Get original content\n const contentStmt = db.prepare('SELECT * FROM content WHERE id = ?')\n const original = await contentStmt.bind(originalId).first() as any\n \n if (!original) {\n return c.json({ success: false, error: 'Content not found' })\n }\n \n // Create duplicate\n const newId = crypto.randomUUID()\n const now = Date.now()\n const originalData = JSON.parse(original.data || '{}')\n \n // Modify title to indicate it's a copy\n originalData.title = `${originalData.title || 'Untitled'} (Copy)`\n \n const insertStmt = db.prepare(`\n INSERT INTO content (\n id, collection_id, slug, title, data, status,\n author_id, created_at, updated_at\n )\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)\n `)\n\n await insertStmt.bind(\n newId,\n original.collection_id,\n `${original.slug}-copy-${Date.now()}`,\n originalData.title,\n JSON.stringify(originalData),\n 'draft', // Always start as draft\n user?.userId || 'unknown',\n now,\n now\n ).run()\n \n return c.json({ success: true, id: newId })\n } catch (error) {\n console.error('Error duplicating content:', error)\n return c.json({ success: false, error: 'Failed to duplicate content' })\n }\n})\n\n// Get bulk actions modal\nadminContentRoutes.get('/bulk-actions', async (c) => {\n const bulkActionsModal = `\n <div class=\"fixed inset-0 bg-zinc-950/50 dark:bg-zinc-950/80 backdrop-blur-sm z-50 flex items-center justify-center p-4\" onclick=\"this.remove()\">\n <div class=\"bg-white dark:bg-zinc-900 rounded-xl shadow-xl ring-1 ring-zinc-950/5 dark:ring-white/10 p-6 max-w-md w-full\" onclick=\"event.stopPropagation()\">\n <div class=\"flex items-center justify-between mb-4\">\n <h3 class=\"text-lg font-semibold text-zinc-950 dark:text-white\">Bulk Actions</h3>\n <button onclick=\"this.closest('.fixed').remove()\" class=\"text-zinc-500 hover:text-zinc-700 dark:text-zinc-400 dark:hover:text-zinc-200\">\n <svg class=\"h-5 w-5\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M6 18L18 6M6 6l12 12\"/>\n </svg>\n </button>\n </div>\n <p class=\"text-sm text-zinc-600 dark:text-zinc-400 mb-4\">\n Select items from the table below to perform bulk actions.\n </p>\n <div class=\"space-y-2\">\n <button\n onclick=\"performBulkAction('publish')\"\n class=\"w-full inline-flex items-center justify-center gap-x-2 px-4 py-2.5 bg-lime-600 dark:bg-lime-500 text-white rounded-lg hover:bg-lime-700 dark:hover:bg-lime-600 transition-colors\"\n >\n <svg class=\"h-5 w-5\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M5 13l4 4L19 7\"/>\n </svg>\n Publish Selected\n </button>\n <button\n onclick=\"performBulkAction('draft')\"\n class=\"w-full inline-flex items-center justify-center gap-x-2 px-4 py-2.5 bg-zinc-600 dark:bg-zinc-700 text-white rounded-lg hover:bg-zinc-700 dark:hover:bg-zinc-800 transition-colors\"\n >\n <svg class=\"h-5 w-5\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M15.232 5.232l3.536 3.536m-2.036-5.036a2.5 2.5 0 113.536 3.536L6.5 21.036H3v-3.572L16.732 3.732z\"/>\n </svg>\n Move to Draft\n </button>\n <button\n onclick=\"performBulkAction('delete')\"\n class=\"w-full inline-flex items-center justify-center gap-x-2 px-4 py-2.5 bg-red-600 dark:bg-red-500 text-white rounded-lg hover:bg-red-700 dark:hover:bg-red-600 transition-colors\"\n >\n <svg class=\"h-5 w-5\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16\"/>\n </svg>\n Delete Selected\n </button>\n </div>\n </div>\n </div>\n <script>\n function performBulkAction(action) {\n const selectedIds = Array.from(document.querySelectorAll('input[type=\"checkbox\"].row-checkbox:checked'))\n .map(cb => cb.value)\n .filter(id => id)\n\n if (selectedIds.length === 0) {\n alert('Please select at least one item')\n return\n }\n\n const actionText = action === 'publish' ? 'publish' : action === 'draft' ? 'move to draft' : 'delete'\n const confirmed = confirm(\\`Are you sure you want to \\${actionText} \\${selectedIds.length} item(s)?\\`)\n\n if (!confirmed) return\n\n fetch('/admin/content/bulk-action', {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json'\n },\n body: JSON.stringify({\n action: action,\n ids: selectedIds\n })\n })\n .then(res => res.json())\n .then(data => {\n if (data.success) {\n document.querySelector('#bulk-actions-modal .fixed').remove()\n location.reload()\n } else {\n alert('Error: ' + (data.error || 'Unknown error'))\n }\n })\n .catch(err => {\n console.error('Bulk action error:', err)\n alert('Failed to perform bulk action')\n })\n }\n </script>\n `\n\n return c.html(bulkActionsModal)\n})\n\n// Perform bulk action\nadminContentRoutes.post('/bulk-action', async (c) => {\n try {\n const user = c.get('user')\n const body = await c.req.json()\n const { action, ids } = body\n\n if (!action || !ids || ids.length === 0) {\n return c.json({ success: false, error: 'Action and IDs required' })\n }\n\n const db = c.env.DB\n const now = Date.now()\n\n if (action === 'delete') {\n // Soft delete by setting status to 'deleted'\n const placeholders = ids.map(() => '?').join(',')\n const stmt = db.prepare(`\n UPDATE content\n SET status = 'deleted', updated_at = ?\n WHERE id IN (${placeholders})\n `)\n await stmt.bind(now, ...ids).run()\n } else if (action === 'publish' || action === 'draft') {\n // Update status\n const placeholders = ids.map(() => '?').join(',')\n const publishedAt = action === 'publish' ? now : null\n const stmt = db.prepare(`\n UPDATE content\n SET status = ?, published_at = ?, updated_at = ?\n WHERE id IN (${placeholders})\n `)\n await stmt.bind(action, publishedAt, now, ...ids).run()\n } else {\n return c.json({ success: false, error: 'Invalid action' })\n }\n\n // Invalidate cache for all affected content items\n const cache = getCacheService(CACHE_CONFIGS.content!)\n for (const contentId of ids) {\n await cache.delete(cache.generateKey('content', contentId))\n }\n // Also invalidate list caches (they contain content from potentially multiple collections)\n await cache.invalidate('content:list:*')\n\n return c.json({ success: true, count: ids.length })\n } catch (error) {\n console.error('Bulk action error:', error)\n return c.json({ success: false, error: 'Failed to perform bulk action' })\n }\n})\n\n// Delete content\nadminContentRoutes.delete('/:id', async (c) => {\n try {\n const id = c.req.param('id')\n const db = c.env.DB\n const user = c.get('user')\n\n // Check if content exists\n const contentStmt = db.prepare('SELECT id, title FROM content WHERE id = ?')\n const content = await contentStmt.bind(id).first() as any\n\n if (!content) {\n return c.json({ success: false, error: 'Content not found' }, 404)\n }\n\n // Soft delete by setting status to 'deleted'\n const now = Date.now()\n const deleteStmt = db.prepare(`\n UPDATE content\n SET status = 'deleted', updated_at = ?\n WHERE id = ?\n `)\n await deleteStmt.bind(now, id).run()\n\n // Invalidate cache\n const cache = getCacheService(CACHE_CONFIGS.content!)\n await cache.delete(cache.generateKey('content', id))\n await cache.invalidate('content:list:*')\n\n // Return success - let HTMX reload the page\n return c.html(`\n <div id=\"content-list\" hx-get=\"/admin/content?model=${c.req.query('model') || 'post'}\" hx-trigger=\"load\" hx-swap=\"outerHTML\">\n <div class=\"flex items-center justify-center p-8\">\n <div class=\"text-center\">\n <svg class=\"mx-auto h-12 w-12 text-lime-500 dark:text-lime-400\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M5 13l4 4L19 7\"/>\n </svg>\n <p class=\"mt-2 text-sm text-zinc-600 dark:text-zinc-400\">Content deleted successfully. Refreshing...</p>\n </div>\n </div>\n </div>\n `)\n } catch (error) {\n console.error('Delete content error:', error)\n return c.json({ success: false, error: 'Failed to delete content' }, 500)\n }\n})\n\n// Get version history\nadminContentRoutes.get('/:id/versions', async (c) => {\n try {\n const id = c.req.param('id')\n const db = c.env.DB\n \n // Get current content\n const contentStmt = db.prepare('SELECT * FROM content WHERE id = ?')\n const content = await contentStmt.bind(id).first() as any\n \n if (!content) {\n return c.html('<p>Content not found</p>')\n }\n \n // Get all versions with author info\n const versionsStmt = db.prepare(`\n SELECT cv.*, u.first_name, u.last_name, u.email\n FROM content_versions cv\n LEFT JOIN users u ON cv.author_id = u.id\n WHERE cv.content_id = ?\n ORDER BY cv.version DESC\n `)\n const { results } = await versionsStmt.bind(id).all()\n \n const versions: ContentVersion[] = (results || []).map((row: any) => ({\n id: row.id,\n version: row.version,\n data: JSON.parse(row.data || '{}'),\n author_id: row.author_id,\n author_name: row.first_name && row.last_name ? `${row.first_name} ${row.last_name}` : row.email,\n created_at: row.created_at,\n is_current: false // Will be set below\n }))\n \n // Mark the latest version as current\n if (versions.length > 0) {\n versions[0]!.is_current = true\n }\n \n const data: VersionHistoryData = {\n contentId: id,\n versions,\n currentVersion: versions.length > 0 ? versions[0]!.version : 1\n }\n \n return c.html(renderVersionHistory(data))\n } catch (error) {\n console.error('Error loading version history:', error)\n return c.html('<p>Error loading version history</p>')\n }\n})\n\n// Restore version\nadminContentRoutes.post('/:id/restore/:version', async (c) => {\n try {\n const id = c.req.param('id')\n const version = parseInt(c.req.param('version'))\n const user = c.get('user')\n const db = c.env.DB\n \n // Get the specific version\n const versionStmt = db.prepare(`\n SELECT * FROM content_versions \n WHERE content_id = ? AND version = ?\n `)\n const versionData = await versionStmt.bind(id, version).first() as any\n \n if (!versionData) {\n return c.json({ success: false, error: 'Version not found' })\n }\n \n // Get current content\n const contentStmt = db.prepare('SELECT * FROM content WHERE id = ?')\n const currentContent = await contentStmt.bind(id).first() as any\n \n if (!currentContent) {\n return c.json({ success: false, error: 'Content not found' })\n }\n \n const restoredData = JSON.parse(versionData.data)\n const now = Date.now()\n \n // Update content with restored data\n const updateStmt = db.prepare(`\n UPDATE content SET\n title = ?, data = ?, updated_at = ?\n WHERE id = ?\n `)\n \n await updateStmt.bind(\n restoredData.title || 'Untitled',\n versionData.data,\n now,\n id\n ).run()\n \n // Create new version for the restoration\n const nextVersionStmt = db.prepare('SELECT MAX(version) as max_version FROM content_versions WHERE content_id = ?')\n const nextVersionResult = await nextVersionStmt.bind(id).first() as any\n const nextVersion = (nextVersionResult?.max_version || 0) + 1\n \n const newVersionStmt = db.prepare(`\n INSERT INTO content_versions (id, content_id, version, data, author_id, created_at)\n VALUES (?, ?, ?, ?, ?, ?)\n `)\n \n await newVersionStmt.bind(\n crypto.randomUUID(),\n id,\n nextVersion,\n versionData.data,\n user?.userId || 'unknown',\n now\n ).run()\n \n // Log workflow action\n const workflowStmt = db.prepare(`\n INSERT INTO workflow_history (id, content_id, action, from_status, to_status, user_id, comment, created_at)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?)\n `)\n \n await workflowStmt.bind(\n crypto.randomUUID(),\n id,\n 'version_restored',\n currentContent.status,\n currentContent.status,\n user?.userId || 'unknown',\n `Restored to version ${version}`,\n now\n ).run()\n \n return c.json({ success: true })\n } catch (error) {\n console.error('Error restoring version:', error)\n return c.json({ success: false, error: 'Failed to restore version' })\n }\n})\n\n// Preview specific version\nadminContentRoutes.get('/:id/version/:version/preview', async (c) => {\n try {\n const id = c.req.param('id')\n const version = parseInt(c.req.param('version'))\n const db = c.env.DB\n \n // Get the specific version\n const versionStmt = db.prepare(`\n SELECT cv.*, c.collection_id, col.display_name as collection_name\n FROM content_versions cv\n JOIN content c ON cv.content_id = c.id\n JOIN collections col ON c.collection_id = col.id\n WHERE cv.content_id = ? AND cv.version = ?\n `)\n const versionData = await versionStmt.bind(id, version).first() as any\n \n if (!versionData) {\n return c.html('<p>Version not found</p>')\n }\n \n const data = JSON.parse(versionData.data || '{}')\n \n // Generate preview HTML\n const previewHTML = `\n <!DOCTYPE html>\n <html lang=\"en\">\n <head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <title>Version ${version} Preview: ${data.title || 'Untitled'}</title>\n <style>\n body { font-family: Arial, sans-serif; max-width: 800px; margin: 0 auto; padding: 20px; }\n h1 { color: #333; }\n .meta { color: #666; font-size: 14px; margin-bottom: 20px; padding: 10px; background: #f5f5f5; border-radius: 5px; }\n .content { line-height: 1.6; }\n .version-badge { background: #007cba; color: white; padding: 5px 10px; border-radius: 15px; font-size: 12px; }\n </style>\n </head>\n <body>\n <div class=\"meta\">\n <span class=\"version-badge\">Version ${version}</span>\n <strong>Collection:</strong> ${versionData.collection_name}<br>\n <strong>Created:</strong> ${new Date(versionData.created_at).toLocaleString()}<br>\n <em>This is a historical version preview</em>\n </div>\n \n <h1>${data.title || 'Untitled'}</h1>\n \n <div class=\"content\">\n ${data.content || '<p>No content provided.</p>'}\n </div>\n \n ${data.excerpt ? `<h3>Excerpt:</h3><p>${data.excerpt}</p>` : ''}\n \n <h3>All Field Data:</h3>\n <pre style=\"background: #f5f5f5; padding: 15px; border-radius: 5px; overflow-x: auto;\">\n${JSON.stringify(data, null, 2)}\n </pre>\n </body>\n </html>\n `\n \n return c.html(previewHTML)\n } catch (error) {\n console.error('Error generating version preview:', error)\n return c.html('<p>Error generating preview</p>')\n }\n})\nexport default adminContentRoutes\n","import { renderAdminLayoutCatalyst, AdminLayoutCatalystData } from '../layouts/admin-layout-catalyst.template'\nimport { renderAlert } from '../alert.template'\n\nexport interface UserProfile {\n id: string\n email: string\n username: string\n first_name: string\n last_name: string\n phone?: string\n bio?: string\n avatar_url?: string\n timezone: string\n language: string\n theme: string\n email_notifications: boolean\n two_factor_enabled: boolean\n role: string\n created_at: number\n last_login_at?: number\n}\n\nexport interface ProfilePageData {\n profile: UserProfile\n timezones: Array<{ value: string; label: string }>\n languages: Array<{ value: string; label: string }>\n error?: string\n success?: string\n user?: {\n name: string\n email: string\n role: string\n }\n version?: string\n}\n\nexport function renderAvatarImage(avatarUrl: string | undefined, firstName: string, lastName: string): string {\n return `<div id=\"avatar-image-container\" class=\"w-24 h-24 rounded-full mx-auto mb-4 overflow-hidden bg-gradient-to-br from-cyan-400 to-purple-400 flex items-center justify-center ring-4 ring-zinc-950/5 dark:ring-white/10\">\n ${avatarUrl\n ? `<img src=\"${avatarUrl}\" alt=\"Profile picture\" class=\"w-full h-full object-cover\">`\n : `<span class=\"text-2xl font-bold text-white\">${firstName.charAt(0)}${lastName.charAt(0)}</span>`\n }\n </div>`\n}\n\nexport function renderProfilePage(data: ProfilePageData): string {\n const pageContent = `\n <div class=\"space-y-8\">\n <!-- Header -->\n <div class=\"sm:flex sm:items-center sm:justify-between\">\n <div>\n <h1 class=\"text-2xl/8 font-semibold text-zinc-950 dark:text-white sm:text-xl/8\">User Profile</h1>\n <p class=\"mt-2 text-sm/6 text-zinc-500 dark:text-zinc-400\">\n Manage your account settings and preferences\n </p>\n </div>\n </div>\n\n <!-- Alert Messages -->\n ${data.error ? renderAlert({ type: 'error', message: data.error, dismissible: true }) : ''}\n ${data.success ? renderAlert({ type: 'success', message: data.success, dismissible: true }) : ''}\n\n <!-- Profile Form -->\n <div class=\"grid grid-cols-1 lg:grid-cols-3 gap-8\">\n <!-- Main Profile Form -->\n <div class=\"lg:col-span-2\">\n <div class=\"rounded-xl bg-white dark:bg-zinc-900 shadow-sm ring-1 ring-zinc-950/5 dark:ring-white/10\">\n <!-- Form Header -->\n <div class=\"px-6 py-5 border-b border-zinc-950/5 dark:border-white/5\">\n <div class=\"flex items-center gap-x-3\">\n <div class=\"flex h-10 w-10 items-center justify-center rounded-lg bg-zinc-950 dark:bg-white\">\n <svg class=\"h-5 w-5 text-white dark:text-zinc-950\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z\"/>\n </svg>\n </div>\n <div>\n <h2 class=\"text-base font-semibold text-zinc-950 dark:text-white\">Profile Information</h2>\n <p class=\"text-sm text-zinc-500 dark:text-zinc-400\">Update your account details</p>\n </div>\n </div>\n </div>\n\n <!-- Form Content -->\n <form id=\"profile-form\" hx-put=\"/admin/profile\" hx-target=\"#form-messages\" class=\"p-6 space-y-6\">\n <div id=\"form-messages\"></div>\n\n <!-- Basic Information -->\n <div class=\"grid grid-cols-1 md:grid-cols-2 gap-6\">\n <div>\n <label class=\"block text-sm font-medium text-zinc-950 dark:text-white mb-2\">First Name</label>\n <input\n type=\"text\"\n name=\"first_name\"\n value=\"${data.profile.first_name}\"\n required\n class=\"w-full rounded-lg bg-white dark:bg-zinc-800 px-3 py-2 text-sm text-zinc-950 dark:text-white shadow-sm ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 placeholder:text-zinc-400 dark:placeholder:text-zinc-500 focus:outline-none focus:ring-2 focus:ring-zinc-950 dark:focus:ring-white transition-shadow\"\n placeholder=\"Enter your first name\"\n >\n </div>\n <div>\n <label class=\"block text-sm font-medium text-zinc-950 dark:text-white mb-2\">Last Name</label>\n <input\n type=\"text\"\n name=\"last_name\"\n value=\"${data.profile.last_name}\"\n required\n class=\"w-full rounded-lg bg-white dark:bg-zinc-800 px-3 py-2 text-sm text-zinc-950 dark:text-white shadow-sm ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 placeholder:text-zinc-400 dark:placeholder:text-zinc-500 focus:outline-none focus:ring-2 focus:ring-zinc-950 dark:focus:ring-white transition-shadow\"\n placeholder=\"Enter your last name\"\n >\n </div>\n </div>\n\n <div>\n <label class=\"block text-sm font-medium text-zinc-950 dark:text-white mb-2\">Username</label>\n <input\n type=\"text\"\n name=\"username\"\n value=\"${data.profile.username}\"\n required\n class=\"w-full rounded-lg bg-white dark:bg-zinc-800 px-3 py-2 text-sm text-zinc-950 dark:text-white shadow-sm ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 placeholder:text-zinc-400 dark:placeholder:text-zinc-500 focus:outline-none focus:ring-2 focus:ring-zinc-950 dark:focus:ring-white transition-shadow\"\n placeholder=\"Enter your username\"\n >\n </div>\n\n <div>\n <label class=\"block text-sm font-medium text-zinc-950 dark:text-white mb-2\">Email Address</label>\n <input\n type=\"email\"\n name=\"email\"\n value=\"${data.profile.email}\"\n required\n class=\"w-full rounded-lg bg-white dark:bg-zinc-800 px-3 py-2 text-sm text-zinc-950 dark:text-white shadow-sm ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 placeholder:text-zinc-400 dark:placeholder:text-zinc-500 focus:outline-none focus:ring-2 focus:ring-zinc-950 dark:focus:ring-white transition-shadow\"\n placeholder=\"Enter your email address\"\n >\n </div>\n\n <div>\n <label class=\"block text-sm font-medium text-zinc-950 dark:text-white mb-2\">Phone Number</label>\n <input\n type=\"tel\"\n name=\"phone\"\n value=\"${data.profile.phone || ''}\"\n class=\"w-full rounded-lg bg-white dark:bg-zinc-800 px-3 py-2 text-sm text-zinc-950 dark:text-white shadow-sm ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 placeholder:text-zinc-400 dark:placeholder:text-zinc-500 focus:outline-none focus:ring-2 focus:ring-zinc-950 dark:focus:ring-white transition-shadow\"\n placeholder=\"Enter your phone number\"\n >\n </div>\n\n <div>\n <label class=\"block text-sm font-medium text-zinc-950 dark:text-white mb-2\">Bio</label>\n <textarea\n name=\"bio\"\n rows=\"3\"\n class=\"w-full rounded-lg bg-white dark:bg-zinc-800 px-3 py-2 text-sm text-zinc-950 dark:text-white shadow-sm ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 placeholder:text-zinc-400 dark:placeholder:text-zinc-500 focus:outline-none focus:ring-2 focus:ring-zinc-950 dark:focus:ring-white transition-shadow resize-none\"\n placeholder=\"Tell us about yourself...\"\n >${data.profile.bio || ''}</textarea>\n </div>\n\n <!-- Preferences -->\n <div class=\"pt-6 border-t border-zinc-950/5 dark:border-white/5\">\n <h3 class=\"text-base font-semibold text-zinc-950 dark:text-white mb-4\">Preferences</h3>\n\n <div class=\"grid grid-cols-1 md:grid-cols-2 gap-6\">\n <div>\n <label for=\"timezone\" class=\"block text-sm/6 font-medium text-zinc-950 dark:text-white mb-2\">Timezone</label>\n <div class=\"grid grid-cols-1\">\n <select id=\"timezone\" name=\"timezone\" class=\"col-start-1 row-start-1 w-full appearance-none rounded-md bg-white/5 dark:bg-white/5 py-1.5 pl-3 pr-8 text-base text-zinc-950 dark:text-white outline outline-1 -outline-offset-1 outline-zinc-500/30 dark:outline-zinc-400/30 *:bg-white dark:*:bg-zinc-800 focus-visible:outline focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-zinc-500 dark:focus-visible:outline-zinc-400 sm:text-sm/6\">\n ${data.timezones.map(tz => `\n <option value=\"${tz.value}\" ${tz.value === data.profile.timezone ? 'selected' : ''}>${tz.label}</option>\n `).join('')}\n </select>\n <svg viewBox=\"0 0 16 16\" fill=\"currentColor\" aria-hidden=\"true\" class=\"pointer-events-none col-start-1 row-start-1 mr-2 size-5 self-center justify-self-end text-zinc-600 dark:text-zinc-400 sm:size-4\">\n <path d=\"M4.22 6.22a.75.75 0 0 1 1.06 0L8 8.94l2.72-2.72a.75.75 0 1 1 1.06 1.06l-3.25 3.25a.75.75 0 0 1-1.06 0L4.22 7.28a.75.75 0 0 1 0-1.06Z\" clip-rule=\"evenodd\" fill-rule=\"evenodd\" />\n </svg>\n </div>\n </div>\n <div>\n <label for=\"language\" class=\"block text-sm/6 font-medium text-zinc-950 dark:text-white mb-2\">Language</label>\n <div class=\"grid grid-cols-1\">\n <select id=\"language\" name=\"language\" class=\"col-start-1 row-start-1 w-full appearance-none rounded-md bg-white/5 dark:bg-white/5 py-1.5 pl-3 pr-8 text-base text-zinc-950 dark:text-white outline outline-1 -outline-offset-1 outline-zinc-500/30 dark:outline-zinc-400/30 *:bg-white dark:*:bg-zinc-800 focus-visible:outline focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-zinc-500 dark:focus-visible:outline-zinc-400 sm:text-sm/6\">\n ${data.languages.map(lang => `\n <option value=\"${lang.value}\" ${lang.value === data.profile.language ? 'selected' : ''}>${lang.label}</option>\n `).join('')}\n </select>\n <svg viewBox=\"0 0 16 16\" fill=\"currentColor\" aria-hidden=\"true\" class=\"pointer-events-none col-start-1 row-start-1 mr-2 size-5 self-center justify-self-end text-zinc-600 dark:text-zinc-400 sm:size-4\">\n <path d=\"M4.22 6.22a.75.75 0 0 1 1.06 0L8 8.94l2.72-2.72a.75.75 0 1 1 1.06 1.06l-3.25 3.25a.75.75 0 0 1-1.06 0L4.22 7.28a.75.75 0 0 1 0-1.06Z\" clip-rule=\"evenodd\" fill-rule=\"evenodd\" />\n </svg>\n </div>\n </div>\n </div>\n </div>\n\n <!-- Notifications -->\n <div class=\"pt-6 border-t border-zinc-950/5 dark:border-white/5\">\n <h3 class=\"text-base font-semibold text-zinc-950 dark:text-white mb-4\">Notifications</h3>\n\n <div class=\"space-y-5\">\n <div class=\"flex gap-3\">\n <div class=\"flex h-6 shrink-0 items-center\">\n <div class=\"group grid size-4 grid-cols-1\">\n <input\n type=\"checkbox\"\n id=\"email_notifications\"\n name=\"email_notifications\"\n value=\"1\"\n ${data.profile.email_notifications ? 'checked' : ''}\n class=\"col-start-1 row-start-1 appearance-none rounded border border-zinc-950/10 dark:border-white/10 bg-white dark:bg-white/5 checked:border-indigo-500 checked:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-500 disabled:border-zinc-950/5 dark:disabled:border-white/5 disabled:bg-zinc-950/10 dark:disabled:bg-white/10 forced-colors:appearance-auto\"\n />\n <svg viewBox=\"0 0 14 14\" fill=\"none\" class=\"pointer-events-none col-start-1 row-start-1 size-3.5 self-center justify-self-center stroke-white group-has-[:disabled]:stroke-zinc-950/25 dark:group-has-[:disabled]:stroke-white/25\">\n <path d=\"M3 8L6 11L11 3.5\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"opacity-0 group-has-[:checked]:opacity-100\" />\n </svg>\n </div>\n </div>\n <div class=\"text-sm/6\">\n <label for=\"email_notifications\" class=\"font-medium text-zinc-950 dark:text-white\">Email notifications</label>\n <p class=\"text-zinc-500 dark:text-zinc-400\">Receive email updates about new features and product announcements.</p>\n </div>\n </div>\n </div>\n </div>\n\n <!-- Submit Button -->\n <div class=\"pt-6 border-t border-zinc-950/5 dark:border-white/5\">\n <button\n type=\"submit\"\n class=\"inline-flex justify-center items-center gap-x-2 rounded-lg bg-zinc-950 dark:bg-white px-4 py-2.5 text-sm font-semibold text-white dark:text-zinc-950 hover:bg-zinc-800 dark:hover:bg-zinc-100 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-zinc-950 dark:focus-visible:outline-white transition-colors\"\n >\n <svg class=\"h-4 w-4\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M5 13l4 4L19 7\"/>\n </svg>\n Update Profile\n </button>\n </div>\n </form>\n </div>\n </div>\n\n <!-- Profile Sidebar -->\n <div class=\"lg:col-span-1 space-y-6\">\n <!-- Avatar -->\n <div class=\"rounded-xl bg-white dark:bg-zinc-900 shadow-sm ring-1 ring-zinc-950/5 dark:ring-white/10 p-6\">\n <h3 class=\"text-base font-semibold text-zinc-950 dark:text-white mb-4\">Profile Picture</h3>\n\n <div class=\"text-center\">\n ${renderAvatarImage(data.profile.avatar_url, data.profile.first_name, data.profile.last_name)}\n\n <form id=\"avatar-form\" hx-post=\"/admin/profile/avatar\" hx-target=\"#avatar-messages\" hx-encoding=\"multipart/form-data\">\n <input\n type=\"file\"\n name=\"avatar\"\n accept=\"image/*\"\n class=\"hidden\"\n id=\"avatar-input\"\n onchange=\"document.getElementById('avatar-form').dispatchEvent(new Event('submit'))\"\n >\n <label\n for=\"avatar-input\"\n class=\"inline-flex items-center gap-x-2 rounded-lg bg-white dark:bg-zinc-800 px-4 py-2.5 text-sm font-semibold text-zinc-950 dark:text-white shadow-sm ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 hover:bg-zinc-50 dark:hover:bg-zinc-700 transition-colors cursor-pointer\"\n >\n <svg class=\"h-4 w-4\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M3 9a2 2 0 012-2h.93a2 2 0 001.664-.89l.812-1.22A2 2 0 0110.07 4h3.86a2 2 0 011.664.89l.812 1.22A2 2 0 0018.07 7H19a2 2 0 012 2v9a2 2 0 01-2 2H5a2 2 0 01-2-2V9z\"/>\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M15 13a3 3 0 11-6 0 3 3 0 016 0z\"/>\n </svg>\n Change Picture\n </label>\n </form>\n\n <div id=\"avatar-messages\" class=\"mt-3\"></div>\n </div>\n </div>\n\n <!-- Account Info -->\n <div class=\"rounded-xl bg-white dark:bg-zinc-900 shadow-sm ring-1 ring-zinc-950/5 dark:ring-white/10 p-6\">\n <h3 class=\"text-base font-semibold text-zinc-950 dark:text-white mb-4\">Account Information</h3>\n\n <dl class=\"space-y-3 text-sm\">\n <div>\n <dt class=\"text-zinc-500 dark:text-zinc-400\">Role</dt>\n <dd class=\"mt-1\">\n <span class=\"inline-flex items-center rounded-md bg-blue-50 dark:bg-blue-500/10 px-2 py-1 text-xs font-medium text-blue-700 dark:text-blue-400 ring-1 ring-inset ring-blue-700/10 dark:ring-blue-400/20 capitalize\">\n ${data.profile.role}\n </span>\n </dd>\n </div>\n <div>\n <dt class=\"text-zinc-500 dark:text-zinc-400\">Member Since</dt>\n <dd class=\"mt-1 text-zinc-950 dark:text-white\">${new Date(data.profile.created_at).toLocaleDateString()}</dd>\n </div>\n ${data.profile.last_login_at ? `\n <div>\n <dt class=\"text-zinc-500 dark:text-zinc-400\">Last Login</dt>\n <dd class=\"mt-1 text-zinc-950 dark:text-white\">${new Date(data.profile.last_login_at).toLocaleDateString()}</dd>\n </div>\n ` : ''}\n <div>\n <dt class=\"text-zinc-500 dark:text-zinc-400\">Two-Factor Auth</dt>\n <dd class=\"mt-1\">\n ${data.profile.two_factor_enabled\n ? '<span class=\"inline-flex items-center rounded-md bg-green-50 dark:bg-green-500/10 px-2 py-1 text-xs font-medium text-green-700 dark:text-green-400 ring-1 ring-inset ring-green-600/20 dark:ring-green-500/20\">Enabled</span>'\n : '<span class=\"inline-flex items-center rounded-md bg-zinc-50 dark:bg-zinc-800 px-2 py-1 text-xs font-medium text-zinc-600 dark:text-zinc-400 ring-1 ring-inset ring-zinc-500/10 dark:ring-zinc-400/20\">Disabled</span>'\n }\n </dd>\n </div>\n </dl>\n </div>\n\n <!-- Security Actions -->\n <div class=\"rounded-xl bg-white dark:bg-zinc-900 shadow-sm ring-1 ring-zinc-950/5 dark:ring-white/10 p-6\">\n <h3 class=\"text-base font-semibold text-zinc-950 dark:text-white mb-4\">Security</h3>\n\n <div class=\"space-y-2\">\n <button\n type=\"button\"\n onclick=\"showChangePasswordModal()\"\n class=\"w-full text-left flex items-center gap-x-3 px-3 py-2 text-sm text-zinc-950 dark:text-white hover:bg-zinc-50 dark:hover:bg-zinc-800/50 rounded-lg transition-colors\"\n >\n <svg class=\"w-4 h-4 text-zinc-500 dark:text-zinc-400\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M15 7a2 2 0 012 2m4 0a6 6 0 01-7.743 5.743L11 17H9v2H7v2H4a1 1 0 01-1-1v-3.586l4.293-4.293A6 6 0 0119 9z\"/>\n </svg>\n <span class=\"font-medium\">Change Password</span>\n </button>\n\n <button\n type=\"button\"\n onclick=\"toggle2FA()\"\n class=\"w-full text-left flex items-center gap-x-3 px-3 py-2 text-sm text-zinc-950 dark:text-white hover:bg-zinc-50 dark:hover:bg-zinc-800/50 rounded-lg transition-colors\"\n >\n <svg class=\"w-4 h-4 text-zinc-500 dark:text-zinc-400\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z\"/>\n </svg>\n <span class=\"font-medium\">${data.profile.two_factor_enabled ? 'Disable' : 'Enable'} 2FA</span>\n </button>\n </div>\n </div>\n </div>\n </div>\n </div>\n\n <!-- Change Password Modal -->\n <div id=\"password-modal\" class=\"fixed inset-0 bg-zinc-950/50 backdrop-blur-sm flex items-center justify-center z-50 hidden\">\n <div class=\"rounded-xl bg-white dark:bg-zinc-900 shadow-2xl ring-1 ring-zinc-950/5 dark:ring-white/10 w-full max-w-md mx-4\">\n <div class=\"px-6 py-5 border-b border-zinc-950/5 dark:border-white/5\">\n <div class=\"flex items-center justify-between\">\n <h3 class=\"text-base font-semibold text-zinc-950 dark:text-white\">Change Password</h3>\n <button onclick=\"closePasswordModal()\" class=\"text-zinc-500 dark:text-zinc-400 hover:text-zinc-950 dark:hover:text-white transition-colors\">\n <svg class=\"w-5 h-5\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M6 18L18 6M6 6l12 12\"></path>\n </svg>\n </button>\n </div>\n </div>\n\n <form id=\"password-form\" hx-post=\"/admin/profile/password\" hx-target=\"#password-messages\" class=\"p-6 space-y-4\">\n <div id=\"password-messages\"></div>\n\n <div>\n <label class=\"block text-sm font-medium text-zinc-950 dark:text-white mb-2\">Current Password</label>\n <input\n type=\"password\"\n name=\"current_password\"\n required\n class=\"w-full rounded-lg bg-white dark:bg-zinc-800 px-3 py-2 text-sm text-zinc-950 dark:text-white shadow-sm ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 placeholder:text-zinc-400 dark:placeholder:text-zinc-500 focus:outline-none focus:ring-2 focus:ring-zinc-950 dark:focus:ring-white transition-shadow\"\n placeholder=\"Enter current password\"\n >\n </div>\n\n <div>\n <label class=\"block text-sm font-medium text-zinc-950 dark:text-white mb-2\">New Password</label>\n <input\n type=\"password\"\n name=\"new_password\"\n required\n minlength=\"8\"\n class=\"w-full rounded-lg bg-white dark:bg-zinc-800 px-3 py-2 text-sm text-zinc-950 dark:text-white shadow-sm ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 placeholder:text-zinc-400 dark:placeholder:text-zinc-500 focus:outline-none focus:ring-2 focus:ring-zinc-950 dark:focus:ring-white transition-shadow\"\n placeholder=\"Enter new password\"\n >\n <p class=\"mt-1 text-xs text-zinc-500 dark:text-zinc-400\">Must be at least 8 characters</p>\n </div>\n\n <div>\n <label class=\"block text-sm font-medium text-zinc-950 dark:text-white mb-2\">Confirm New Password</label>\n <input\n type=\"password\"\n name=\"confirm_password\"\n required\n minlength=\"8\"\n class=\"w-full rounded-lg bg-white dark:bg-zinc-800 px-3 py-2 text-sm text-zinc-950 dark:text-white shadow-sm ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 placeholder:text-zinc-400 dark:placeholder:text-zinc-500 focus:outline-none focus:ring-2 focus:ring-zinc-950 dark:focus:ring-white transition-shadow\"\n placeholder=\"Confirm new password\"\n >\n </div>\n\n <div class=\"flex justify-end gap-x-3 pt-4 border-t border-zinc-950/5 dark:border-white/5\">\n <button\n type=\"button\"\n onclick=\"closePasswordModal()\"\n class=\"rounded-lg bg-white dark:bg-zinc-800 px-4 py-2.5 text-sm font-semibold text-zinc-950 dark:text-white shadow-sm ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 hover:bg-zinc-50 dark:hover:bg-zinc-700 transition-colors\"\n >\n Cancel\n </button>\n <button\n type=\"submit\"\n class=\"inline-flex items-center gap-x-2 rounded-lg bg-zinc-950 dark:bg-white px-4 py-2.5 text-sm font-semibold text-white dark:text-zinc-950 hover:bg-zinc-800 dark:hover:bg-zinc-100 transition-colors\"\n >\n <svg class=\"h-4 w-4\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M5 13l4 4L19 7\"/>\n </svg>\n Update Password\n </button>\n </div>\n </form>\n </div>\n </div>\n\n <script>\n function showChangePasswordModal() {\n document.getElementById('password-modal').classList.remove('hidden');\n }\n\n function closePasswordModal() {\n document.getElementById('password-modal').classList.add('hidden');\n document.getElementById('password-form').reset();\n }\n\n function toggle2FA() {\n // TODO: Implement 2FA toggle\n alert('Two-factor authentication setup coming soon!');\n }\n\n // Close modal on escape key\n document.addEventListener('keydown', function(e) {\n if (e.key === 'Escape' && !document.getElementById('password-modal').classList.contains('hidden')) {\n closePasswordModal();\n }\n });\n\n // Close modal on backdrop click\n document.getElementById('password-modal').addEventListener('click', function(e) {\n if (e.target === this) {\n closePasswordModal();\n }\n });\n </script>\n `\n\n const layoutData: AdminLayoutCatalystData = {\n title: 'User Profile',\n pageTitle: 'Profile',\n currentPath: '/admin/profile',\n user: data.user,\n version: data.version,\n content: pageContent\n }\n\n return renderAdminLayoutCatalyst(layoutData)\n}\n","export type AlertType = 'success' | 'error' | 'warning' | 'info'\n\nexport interface AlertData {\n type: AlertType\n title?: string\n message: string\n dismissible?: boolean\n className?: string\n icon?: boolean\n}\n\nexport function renderAlert(data: AlertData): string {\n const typeClasses = {\n success: 'bg-green-50 dark:bg-green-500/10 border border-green-600/20 dark:border-green-500/20',\n error: 'bg-error/10 border border-red-600/20 dark:border-red-500/20',\n warning: 'bg-amber-50 dark:bg-amber-500/10 border border-amber-600/20 dark:border-amber-500/20',\n info: 'bg-blue-50 dark:bg-blue-500/10 border border-blue-600/20 dark:border-blue-500/20'\n }\n\n const iconClasses = {\n success: 'text-green-600 dark:text-green-400',\n error: 'text-red-600 dark:text-red-400',\n warning: 'text-amber-600 dark:text-amber-400',\n info: 'text-blue-600 dark:text-blue-400'\n }\n\n const textClasses = {\n success: 'text-green-900 dark:text-green-300',\n error: 'text-red-900 dark:text-red-300',\n warning: 'text-amber-900 dark:text-amber-300',\n info: 'text-blue-900 dark:text-blue-300'\n }\n\n const messageTextClasses = {\n success: 'text-green-700 dark:text-green-400',\n error: 'text-red-700 dark:text-red-400',\n warning: 'text-amber-700 dark:text-amber-400',\n info: 'text-blue-700 dark:text-blue-400'\n }\n\n const icons = {\n success: `<path fill-rule=\"evenodd\" d=\"M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z\" clip-rule=\"evenodd\" />`,\n error: `<path fill-rule=\"evenodd\" d=\"M10 18a8 8 0 100-16 8 8 0 000 16zM8.707 7.293a1 1 0 00-1.414 1.414L8.586 10l-1.293 1.293a1 1 0 101.414 1.414L10 11.414l1.293 1.293a1 1 0 001.414-1.414L11.414 10l1.293-1.293a1 1 0 00-1.414-1.414L10 8.586 8.707 7.293z\" clip-rule=\"evenodd\" />`,\n warning: `<path fill-rule=\"evenodd\" d=\"M8.257 3.099c.765-1.36 2.722-1.36 3.486 0l5.58 9.92c.75 1.334-.213 2.98-1.742 2.98H4.42c-1.53 0-2.493-1.646-1.743-2.98l5.58-9.92zM11 13a1 1 0 11-2 0 1 1 0 012 0zm-1-8a1 1 0 00-1 1v3a1 1 0 002 0V6a1 1 0 00-1-1z\" clip-rule=\"evenodd\" />`,\n info: `<path fill-rule=\"evenodd\" d=\"M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7-4a1 1 0 11-2 0 1 1 0 012 0zM9 9a1 1 0 000 2v3a1 1 0 001 1h1a1 1 0 100-2v-3a1 1 0 00-1-1H9z\" clip-rule=\"evenodd\" />`\n }\n\n return `\n <div class=\"rounded-lg p-4 ${typeClasses[data.type]} ${data.className || ''}\" ${data.dismissible ? 'id=\"dismissible-alert\"' : ''}>\n <div class=\"flex\">\n ${data.icon !== false ? `\n <div class=\"flex-shrink-0\">\n <svg class=\"h-5 w-5 ${iconClasses[data.type]}\" viewBox=\"0 0 20 20\" fill=\"currentColor\">\n ${icons[data.type]}\n </svg>\n </div>\n ` : ''}\n <div class=\"${data.icon !== false ? 'ml-3' : ''}\">\n ${data.title ? `\n <h3 class=\"text-sm font-semibold ${textClasses[data.type]}\">\n ${data.title}\n </h3>\n ` : ''}\n <div class=\"${data.title ? 'mt-1 text-sm' : 'text-sm'} ${messageTextClasses[data.type]}\">\n <p>${data.message}</p>\n </div>\n </div>\n ${data.dismissible ? `\n <div class=\"ml-auto pl-3\">\n <div class=\"-mx-1.5 -my-1.5\">\n <button\n type=\"button\"\n class=\"inline-flex rounded-md p-1.5 ${iconClasses[data.type]} hover:bg-opacity-20 focus:outline-none focus:ring-2 focus:ring-offset-2\"\n onclick=\"document.getElementById('dismissible-alert').remove()\"\n >\n <span class=\"sr-only\">Dismiss</span>\n <svg class=\"h-5 w-5\" viewBox=\"0 0 20 20\" fill=\"currentColor\">\n <path fill-rule=\"evenodd\" d=\"M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z\" clip-rule=\"evenodd\" />\n </svg>\n </button>\n </div>\n </div>\n ` : ''}\n </div>\n </div>\n `\n}\n\nexport function renderSuccessAlert(message: string, title?: string): string {\n return renderAlert({ type: 'success', message, title })\n}\n\nexport function renderErrorAlert(message: string, title?: string): string {\n return renderAlert({ type: 'error', message, title })\n}\n\nexport function renderWarningAlert(message: string, title?: string): string {\n return renderAlert({ type: 'warning', message, title })\n}\n\nexport function renderInfoAlert(message: string, title?: string): string {\n return renderAlert({ type: 'info', message, title })\n}\n","import { renderAdminLayout, AdminLayoutData } from '../layouts/admin-layout-v2.template'\n\nexport interface ActivityLog {\n id: string\n user_id: string\n action: string\n resource_type?: string\n resource_id?: string\n details?: any\n ip_address?: string\n user_agent?: string\n created_at: number\n user_email?: string\n user_name?: string\n}\n\nexport interface ActivityLogsPageData {\n logs: ActivityLog[]\n pagination: {\n page: number\n limit: number\n total: number\n pages: number\n }\n filters: {\n user_id?: string\n action?: string\n resource_type?: string\n date_from?: string\n date_to?: string\n }\n user?: {\n name: string\n email: string\n role: string\n }\n}\n\nexport function renderActivityLogsPage(data: ActivityLogsPageData): string {\n const pageContent = `\n <div class=\"w-full px-4 sm:px-6 lg:px-8 py-6\">\n <!-- Header -->\n <div class=\"flex flex-col sm:flex-row sm:items-center sm:justify-between mb-6\">\n <div>\n <h1 class=\"text-2xl font-semibold text-white\">Activity Logs</h1>\n <p class=\"mt-2 text-sm text-gray-300\">Monitor user actions and system activity</p>\n </div>\n </div>\n\n <!-- Breadcrumb -->\n <nav class=\"flex mb-6\" aria-label=\"Breadcrumb\">\n <ol class=\"flex items-center space-x-3\">\n <li>\n <a href=\"/admin\" class=\"text-gray-300 hover:text-white transition-colors\">\n <svg class=\"h-5 w-5\" fill=\"currentColor\" viewBox=\"0 0 20 20\">\n <path d=\"M10.707 2.293a1 1 0 00-1.414 0l-7 7a1 1 0 001.414 1.414L4 10.414V17a1 1 0 001 1h2a1 1 0 001-1v-2a1 1 0 011-1h2a1 1 0 011 1v2a1 1 0 001 1h2a1 1 0 001-1v-6.586l.293.293a1 1 0 001.414-1.414l-7-7z\"/>\n </svg>\n </a>\n </li>\n <li class=\"flex items-center\">\n <svg class=\"h-5 w-5 text-gray-400 mx-2\" fill=\"currentColor\" viewBox=\"0 0 20 20\">\n <path fill-rule=\"evenodd\" d=\"M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z\" clip-rule=\"evenodd\"/>\n </svg>\n <span class=\"text-sm font-medium text-gray-200\">Activity Logs</span>\n </li>\n </ol>\n </nav>\n\n <!-- Filters -->\n <div class=\"backdrop-blur-xl bg-white/10 rounded-xl border border-white/20 shadow-2xl p-6 mb-6\">\n <h3 class=\"text-lg font-semibold text-white mb-4\">Filters</h3>\n \n <form method=\"GET\" action=\"/admin/activity-logs\" class=\"grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4\">\n <div>\n <label class=\"block text-sm font-medium text-gray-300 mb-2\">Action</label>\n <select name=\"action\" class=\"w-full px-3 py-2 bg-white/5 backdrop-blur-sm border border-white/10 rounded-xl text-white focus:outline-none focus:bg-white/10 focus:border-white/30\">\n <option value=\"\">All Actions</option>\n <option value=\"user.login\" ${data.filters.action === 'user.login' ? 'selected' : ''}>User Login</option>\n <option value=\"user.logout\" ${data.filters.action === 'user.logout' ? 'selected' : ''}>User Logout</option>\n <option value=\"user.invite_sent\" ${data.filters.action === 'user.invite_sent' ? 'selected' : ''}>User Invited</option>\n <option value=\"user.invitation_accepted\" ${data.filters.action === 'user.invitation_accepted' ? 'selected' : ''}>Invitation Accepted</option>\n <option value=\"profile.update\" ${data.filters.action === 'profile.update' ? 'selected' : ''}>Profile Update</option>\n <option value=\"profile.password_change\" ${data.filters.action === 'profile.password_change' ? 'selected' : ''}>Password Change</option>\n <option value=\"content.create\" ${data.filters.action === 'content.create' ? 'selected' : ''}>Content Created</option>\n <option value=\"content.update\" ${data.filters.action === 'content.update' ? 'selected' : ''}>Content Updated</option>\n <option value=\"content.delete\" ${data.filters.action === 'content.delete' ? 'selected' : ''}>Content Deleted</option>\n <option value=\"collection.create\" ${data.filters.action === 'collection.create' ? 'selected' : ''}>Collection Created</option>\n <option value=\"collection.update\" ${data.filters.action === 'collection.update' ? 'selected' : ''}>Collection Updated</option>\n </select>\n </div>\n\n <div>\n <label class=\"block text-sm font-medium text-gray-300 mb-2\">Resource Type</label>\n <select name=\"resource_type\" class=\"w-full px-3 py-2 bg-white/5 backdrop-blur-sm border border-white/10 rounded-xl text-white focus:outline-none focus:bg-white/10 focus:border-white/30\">\n <option value=\"\">All Resources</option>\n <option value=\"users\" ${data.filters.resource_type === 'users' ? 'selected' : ''}>Users</option>\n <option value=\"content\" ${data.filters.resource_type === 'content' ? 'selected' : ''}>Content</option>\n <option value=\"collections\" ${data.filters.resource_type === 'collections' ? 'selected' : ''}>Collections</option>\n <option value=\"media\" ${data.filters.resource_type === 'media' ? 'selected' : ''}>Media</option>\n <option value=\"settings\" ${data.filters.resource_type === 'settings' ? 'selected' : ''}>Settings</option>\n </select>\n </div>\n\n <div>\n <label class=\"block text-sm font-medium text-gray-300 mb-2\">From Date</label>\n <input \n type=\"date\" \n name=\"date_from\" \n value=\"${data.filters.date_from || ''}\"\n class=\"w-full px-3 py-2 bg-white/5 backdrop-blur-sm border border-white/10 rounded-xl text-white focus:outline-none focus:bg-white/10 focus:border-white/30\"\n >\n </div>\n\n <div>\n <label class=\"block text-sm font-medium text-gray-300 mb-2\">To Date</label>\n <input \n type=\"date\" \n name=\"date_to\" \n value=\"${data.filters.date_to || ''}\"\n class=\"w-full px-3 py-2 bg-white/5 backdrop-blur-sm border border-white/10 rounded-xl text-white focus:outline-none focus:bg-white/10 focus:border-white/30\"\n >\n </div>\n\n <div class=\"md:col-span-2 lg:col-span-4 flex gap-3\">\n <button \n type=\"submit\"\n class=\"px-6 py-2 bg-gradient-to-r from-blue-600 to-purple-600 text-white font-medium rounded-xl hover:from-blue-700 hover:to-purple-700 transition-all\"\n >\n Apply Filters\n </button>\n <a \n href=\"/admin/activity-logs\"\n class=\"px-6 py-2 bg-white/10 text-white rounded-xl border border-white/20 hover:bg-white/20 transition-all\"\n >\n Clear Filters\n </a>\n </div>\n </form>\n </div>\n\n <!-- Activity Logs Table -->\n <div class=\"backdrop-blur-xl bg-white/10 rounded-xl border border-white/20 shadow-2xl overflow-hidden\">\n <div class=\"relative px-6 py-4 border-b border-white/10\">\n <div class=\"absolute inset-0 bg-gradient-to-r from-blue-600/10 via-purple-600/10 to-pink-600/10\"></div>\n <div class=\"relative flex items-center justify-between\">\n <h2 class=\"text-xl font-semibold text-white\">Recent Activity</h2>\n <div class=\"text-sm text-gray-300\">\n Showing ${data.logs.length} of ${data.pagination.total} logs\n </div>\n </div>\n </div>\n\n <div class=\"overflow-x-auto\">\n <table class=\"w-full\">\n <thead class=\"bg-white/5\">\n <tr>\n <th class=\"px-6 py-3 text-left text-xs font-medium text-gray-300 uppercase tracking-wider\">Timestamp</th>\n <th class=\"px-6 py-3 text-left text-xs font-medium text-gray-300 uppercase tracking-wider\">User</th>\n <th class=\"px-6 py-3 text-left text-xs font-medium text-gray-300 uppercase tracking-wider\">Action</th>\n <th class=\"px-6 py-3 text-left text-xs font-medium text-gray-300 uppercase tracking-wider\">Resource</th>\n <th class=\"px-6 py-3 text-left text-xs font-medium text-gray-300 uppercase tracking-wider\">IP Address</th>\n <th class=\"px-6 py-3 text-left text-xs font-medium text-gray-300 uppercase tracking-wider\">Details</th>\n </tr>\n </thead>\n <tbody class=\"divide-y divide-white/10\">\n ${data.logs.map(log => `\n <tr class=\"hover:bg-white/5 transition-colors\">\n <td class=\"px-6 py-4 whitespace-nowrap text-sm text-gray-300\">\n ${new Date(log.created_at).toLocaleString()}\n </td>\n <td class=\"px-6 py-4 whitespace-nowrap\">\n <div class=\"text-sm text-white\">${log.user_name || 'Unknown'}</div>\n <div class=\"text-xs text-gray-400\">${log.user_email || 'N/A'}</div>\n </td>\n <td class=\"px-6 py-4 whitespace-nowrap\">\n <span class=\"inline-flex px-2 py-1 text-xs font-medium rounded-full ${getActionBadgeClass(log.action)}\">\n ${formatAction(log.action)}\n </span>\n </td>\n <td class=\"px-6 py-4 whitespace-nowrap text-sm text-gray-300\">\n ${log.resource_type ? `\n <div class=\"text-white\">${log.resource_type}</div>\n ${log.resource_id ? `<div class=\"text-xs text-gray-400\">${log.resource_id}</div>` : ''}\n ` : 'N/A'}\n </td>\n <td class=\"px-6 py-4 whitespace-nowrap text-sm text-gray-300\">\n ${log.ip_address || 'N/A'}\n </td>\n <td class=\"px-6 py-4 text-sm text-gray-300\">\n ${log.details ? `\n <details class=\"cursor-pointer\">\n <summary class=\"text-blue-400 hover:text-blue-300\">View Details</summary>\n <pre class=\"mt-2 text-xs bg-black/20 p-2 rounded overflow-x-auto\">${JSON.stringify(log.details, null, 2)}</pre>\n </details>\n ` : 'N/A'}\n </td>\n </tr>\n `).join('')}\n </tbody>\n </table>\n </div>\n\n ${data.logs.length === 0 ? `\n <div class=\"text-center py-12\">\n <svg class=\"mx-auto h-12 w-12 text-gray-400\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z\"/>\n </svg>\n <h3 class=\"mt-2 text-sm font-medium text-gray-300\">No activity logs found</h3>\n <p class=\"mt-1 text-sm text-gray-500\">Try adjusting your filters or check back later.</p>\n </div>\n ` : ''}\n\n <!-- Pagination -->\n ${data.pagination.pages > 1 ? `\n <div class=\"px-6 py-4 border-t border-white/10 flex items-center justify-between\">\n <div class=\"text-sm text-gray-300\">\n Page ${data.pagination.page} of ${data.pagination.pages} (${data.pagination.total} total logs)\n </div>\n <div class=\"flex space-x-2\">\n ${data.pagination.page > 1 ? `\n <a href=\"?page=${data.pagination.page - 1}&${new URLSearchParams(data.filters as Record<string, string>).toString()}\" \n class=\"px-3 py-1 bg-white/10 text-white rounded-lg border border-white/20 hover:bg-white/20 transition-all\">\n Previous\n </a>\n ` : ''}\n ${data.pagination.page < data.pagination.pages ? `\n <a href=\"?page=${data.pagination.page + 1}&${new URLSearchParams(data.filters as Record<string, string>).toString()}\" \n class=\"px-3 py-1 bg-white/10 text-white rounded-lg border border-white/20 hover:bg-white/20 transition-all\">\n Next\n </a>\n ` : ''}\n </div>\n </div>\n ` : ''}\n </div>\n </div>\n `\n\n const layoutData: AdminLayoutData = {\n title: 'Activity Logs',\n pageTitle: 'Activity Logs',\n currentPath: '/admin/activity-logs',\n user: data.user,\n content: pageContent\n }\n\n return renderAdminLayout(layoutData)\n}\n\nfunction getActionBadgeClass(action: string): string {\n if (action.includes('login') || action.includes('logout')) {\n return 'bg-blue-500/20 text-blue-300'\n } else if (action.includes('create') || action.includes('invite')) {\n return 'bg-green-500/20 text-green-300'\n } else if (action.includes('update') || action.includes('change')) {\n return 'bg-yellow-500/20 text-yellow-300'\n } else if (action.includes('delete') || action.includes('cancel')) {\n return 'bg-red-500/20 text-red-300'\n } else {\n return 'bg-gray-500/20 text-gray-300'\n }\n}\n\nfunction formatAction(action: string): string {\n // Convert action from dot notation to readable format\n return action\n .split('.')\n .map(part => part.replace(/_/g, ' ').replace(/\\b\\w/g, l => l.toUpperCase()))\n .join(' - ')\n}","import { renderAdminLayoutCatalyst, AdminLayoutCatalystData } from '../layouts/admin-layout-catalyst.template'\nimport { renderAlert } from '../alert.template'\nimport { renderConfirmationDialog, getConfirmationDialogScript } from '../components/confirmation-dialog.template'\nimport { escapeHtml } from '../../utils/sanitize'\n\nexport interface UserEditData {\n id: string\n email: string\n username: string\n firstName: string\n lastName: string\n phone?: string\n bio?: string\n avatarUrl?: string\n role: string\n isActive: boolean\n emailVerified: boolean\n twoFactorEnabled: boolean\n createdAt: number\n lastLoginAt?: number\n}\n\nexport interface UserEditPageData {\n userToEdit: UserEditData\n roles: Array<{ value: string; label: string }>\n error?: string\n success?: string\n user?: {\n name: string\n email: string\n role: string\n }\n}\n\nexport function renderUserEditPage(data: UserEditPageData): string {\n const pageContent = `\n <div>\n <!-- Header -->\n <div class=\"flex flex-col sm:flex-row sm:items-center sm:justify-between mb-6\">\n <div>\n <div class=\"flex items-center gap-3 mb-2\">\n <a href=\"/admin/users\" class=\"text-zinc-500 dark:text-zinc-400 hover:text-zinc-950 dark:hover:text-white transition-colors\">\n <svg class=\"h-5 w-5\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M15 19l-7-7 7-7\"/>\n </svg>\n </a>\n <h1 class=\"text-2xl/8 font-semibold text-zinc-950 dark:text-white sm:text-xl/8\">Edit User</h1>\n </div>\n <p class=\"mt-2 text-sm/6 text-zinc-500 dark:text-zinc-400\">Update user account and permissions</p>\n </div>\n <div class=\"mt-4 sm:mt-0 sm:ml-16 sm:flex-none flex space-x-3\">\n <button\n type=\"submit\"\n form=\"user-edit-form\"\n class=\"inline-flex items-center justify-center rounded-lg bg-zinc-950 dark:bg-white px-3.5 py-2.5 text-sm font-semibold text-white dark:text-zinc-950 hover:bg-zinc-800 dark:hover:bg-zinc-100 transition-colors shadow-sm\"\n >\n <svg class=\"-ml-0.5 mr-1.5 h-5 w-5\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M5 13l4 4L19 7\"/>\n </svg>\n Save Changes\n </button>\n <a\n href=\"/admin/users\"\n class=\"inline-flex items-center justify-center rounded-lg bg-white dark:bg-zinc-800 px-3.5 py-2.5 text-sm font-semibold text-zinc-950 dark:text-white ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 hover:bg-zinc-50 dark:hover:bg-zinc-700 transition-colors shadow-sm\"\n >\n Cancel\n </a>\n </div>\n </div>\n\n <!-- Alert Messages -->\n <div id=\"form-messages\">\n ${data.error ? renderAlert({ type: 'error', message: data.error, dismissible: true }) : ''}\n ${data.success ? renderAlert({ type: 'success', message: data.success, dismissible: true }) : ''}\n </div>\n\n <!-- User Edit Form -->\n <div class=\"grid grid-cols-1 lg:grid-cols-3 gap-6\">\n <!-- Main Form -->\n <div class=\"lg:col-span-2\">\n <div class=\"rounded-xl bg-white dark:bg-zinc-900 shadow-sm ring-1 ring-zinc-950/5 dark:ring-white/10 p-8\">\n <form id=\"user-edit-form\" hx-put=\"/admin/users/${data.userToEdit.id}\" hx-target=\"#form-messages\">\n\n <!-- Basic Information -->\n <div class=\"mb-8\">\n <h3 class=\"text-base font-semibold text-zinc-950 dark:text-white mb-4\">Basic Information</h3>\n <div class=\"grid grid-cols-1 md:grid-cols-2 gap-6\">\n <div>\n <label class=\"block text-sm font-medium text-zinc-950 dark:text-white mb-2\">First Name</label>\n <input\n type=\"text\"\n name=\"first_name\"\n value=\"${escapeHtml(data.userToEdit.firstName || '')}\"\n required\n class=\"w-full rounded-lg bg-white dark:bg-zinc-800 px-3 py-2 text-sm text-zinc-950 dark:text-white shadow-sm ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 placeholder:text-zinc-400 dark:placeholder:text-zinc-500 focus:outline-none focus:ring-2 focus:ring-zinc-950 dark:focus:ring-white transition-shadow\"\n />\n </div>\n\n <div>\n <label class=\"block text-sm font-medium text-zinc-950 dark:text-white mb-2\">Last Name</label>\n <input\n type=\"text\"\n name=\"last_name\"\n value=\"${escapeHtml(data.userToEdit.lastName || '')}\"\n required\n class=\"w-full rounded-lg bg-white dark:bg-zinc-800 px-3 py-2 text-sm text-zinc-950 dark:text-white shadow-sm ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 placeholder:text-zinc-400 dark:placeholder:text-zinc-500 focus:outline-none focus:ring-2 focus:ring-zinc-950 dark:focus:ring-white transition-shadow\"\n />\n </div>\n\n <div>\n <label class=\"block text-sm font-medium text-zinc-950 dark:text-white mb-2\">Username</label>\n <input\n type=\"text\"\n name=\"username\"\n value=\"${escapeHtml(data.userToEdit.username || '')}\"\n required\n class=\"w-full rounded-lg bg-white dark:bg-zinc-800 px-3 py-2 text-sm text-zinc-950 dark:text-white shadow-sm ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 placeholder:text-zinc-400 dark:placeholder:text-zinc-500 focus:outline-none focus:ring-2 focus:ring-zinc-950 dark:focus:ring-white transition-shadow\"\n />\n </div>\n\n <div>\n <label class=\"block text-sm font-medium text-zinc-950 dark:text-white mb-2\">Email</label>\n <input\n type=\"email\"\n name=\"email\"\n value=\"${escapeHtml(data.userToEdit.email || '')}\"\n required\n class=\"w-full rounded-lg bg-white dark:bg-zinc-800 px-3 py-2 text-sm text-zinc-950 dark:text-white shadow-sm ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 placeholder:text-zinc-400 dark:placeholder:text-zinc-500 focus:outline-none focus:ring-2 focus:ring-zinc-950 dark:focus:ring-white transition-shadow\"\n />\n </div>\n\n <div>\n <label class=\"block text-sm font-medium text-zinc-950 dark:text-white mb-2\">Phone</label>\n <input\n type=\"tel\"\n name=\"phone\"\n value=\"${escapeHtml(data.userToEdit.phone || '')}\"\n class=\"w-full rounded-lg bg-white dark:bg-zinc-800 px-3 py-2 text-sm text-zinc-950 dark:text-white shadow-sm ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 placeholder:text-zinc-400 dark:placeholder:text-zinc-500 focus:outline-none focus:ring-2 focus:ring-zinc-950 dark:focus:ring-white transition-shadow\"\n />\n </div>\n\n <div>\n <label for=\"role\" class=\"block text-sm/6 font-medium text-zinc-950 dark:text-white\">Role</label>\n <div class=\"mt-2 grid grid-cols-1\">\n <select\n id=\"role\"\n name=\"role\"\n class=\"col-start-1 row-start-1 w-full appearance-none rounded-md bg-white/5 dark:bg-white/5 py-1.5 pl-3 pr-8 text-base text-zinc-950 dark:text-white outline outline-1 -outline-offset-1 outline-zinc-500/30 dark:outline-zinc-400/30 *:bg-white dark:*:bg-zinc-800 focus-visible:outline focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-zinc-500 dark:focus-visible:outline-zinc-400 sm:text-sm/6\"\n >\n ${data.roles.map(role => `\n <option value=\"${escapeHtml(role.value)}\" ${data.userToEdit.role === role.value ? 'selected' : ''}>${escapeHtml(role.label)}</option>\n `).join('')}\n </select>\n <svg viewBox=\"0 0 16 16\" fill=\"currentColor\" data-slot=\"icon\" aria-hidden=\"true\" class=\"pointer-events-none col-start-1 row-start-1 mr-2 size-5 self-center justify-self-end text-zinc-600 dark:text-zinc-400 sm:size-4\">\n <path d=\"M4.22 6.22a.75.75 0 0 1 1.06 0L8 8.94l2.72-2.72a.75.75 0 1 1 1.06 1.06l-3.25 3.25a.75.75 0 0 1-1.06 0L4.22 7.28a.75.75 0 0 1 0-1.06Z\" clip-rule=\"evenodd\" fill-rule=\"evenodd\" />\n </svg>\n </div>\n </div>\n </div>\n\n <div class=\"mt-6\">\n <label class=\"block text-sm font-medium text-zinc-950 dark:text-white mb-2\">Bio</label>\n <textarea\n name=\"bio\"\n rows=\"3\"\n class=\"w-full rounded-lg bg-white dark:bg-zinc-800 px-3 py-2 text-sm text-zinc-950 dark:text-white shadow-sm ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 placeholder:text-zinc-400 dark:placeholder:text-zinc-500 focus:outline-none focus:ring-2 focus:ring-zinc-950 dark:focus:ring-white transition-shadow\"\n >${escapeHtml(data.userToEdit.bio || '')}</textarea>\n </div>\n </div>\n\n <!-- Account Status -->\n <div class=\"mb-8\">\n <h3 class=\"text-base font-semibold text-zinc-950 dark:text-white mb-4\">Account Status</h3>\n <div class=\"space-y-4\">\n <div class=\"flex gap-3\">\n <div class=\"flex h-6 shrink-0 items-center\">\n <div class=\"group grid size-4 grid-cols-1\">\n <input\n type=\"checkbox\"\n id=\"is_active\"\n name=\"is_active\"\n value=\"1\"\n ${data.userToEdit.isActive ? 'checked' : ''}\n class=\"col-start-1 row-start-1 appearance-none rounded border border-zinc-950/10 dark:border-white/10 bg-white dark:bg-white/5 checked:border-indigo-500 checked:bg-indigo-500 indeterminate:border-indigo-500 indeterminate:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-500 disabled:border-zinc-950/5 dark:disabled:border-white/5 disabled:bg-zinc-950/10 dark:disabled:bg-white/10 disabled:checked:bg-zinc-950/10 dark:disabled:checked:bg-white/10 forced-colors:appearance-auto\"\n />\n <svg viewBox=\"0 0 14 14\" fill=\"none\" class=\"pointer-events-none col-start-1 row-start-1 size-3.5 self-center justify-self-center stroke-white group-has-[:disabled]:stroke-zinc-950/25 dark:group-has-[:disabled]:stroke-white/25\">\n <path d=\"M3 8L6 11L11 3.5\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"opacity-0 group-has-[:checked]:opacity-100\" />\n <path d=\"M3 7H11\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"opacity-0 group-has-[:indeterminate]:opacity-100\" />\n </svg>\n </div>\n </div>\n <div class=\"text-sm/6\">\n <label for=\"is_active\" class=\"font-medium text-zinc-950 dark:text-white\">Account Active</label>\n <p class=\"text-zinc-500 dark:text-zinc-400\">User can sign in and access the system</p>\n </div>\n </div>\n\n <div class=\"flex gap-3\">\n <div class=\"flex h-6 shrink-0 items-center\">\n <div class=\"group grid size-4 grid-cols-1\">\n <input\n type=\"checkbox\"\n id=\"email_verified\"\n name=\"email_verified\"\n value=\"1\"\n ${data.userToEdit.emailVerified ? 'checked' : ''}\n class=\"col-start-1 row-start-1 appearance-none rounded border border-zinc-950/10 dark:border-white/10 bg-white dark:bg-white/5 checked:border-indigo-500 checked:bg-indigo-500 indeterminate:border-indigo-500 indeterminate:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-500 disabled:border-zinc-950/5 dark:disabled:border-white/5 disabled:bg-zinc-950/10 dark:disabled:bg-white/10 disabled:checked:bg-zinc-950/10 dark:disabled:checked:bg-white/10 forced-colors:appearance-auto\"\n />\n <svg viewBox=\"0 0 14 14\" fill=\"none\" class=\"pointer-events-none col-start-1 row-start-1 size-3.5 self-center justify-self-center stroke-white group-has-[:disabled]:stroke-zinc-950/25 dark:group-has-[:disabled]:stroke-white/25\">\n <path d=\"M3 8L6 11L11 3.5\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"opacity-0 group-has-[:checked]:opacity-100\" />\n <path d=\"M3 7H11\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"opacity-0 group-has-[:indeterminate]:opacity-100\" />\n </svg>\n </div>\n </div>\n <div class=\"text-sm/6\">\n <label for=\"email_verified\" class=\"font-medium text-zinc-950 dark:text-white\">Email Verified</label>\n <p class=\"text-zinc-500 dark:text-zinc-400\">User has verified their email address</p>\n </div>\n </div>\n </div>\n </div>\n\n </form>\n </div>\n </div>\n\n <!-- Sidebar -->\n <div class=\"lg:col-span-1\">\n <!-- User Stats -->\n <div class=\"rounded-xl bg-white dark:bg-zinc-900 shadow-sm ring-1 ring-zinc-950/5 dark:ring-white/10 p-6 mb-6\">\n <h3 class=\"text-base font-semibold text-zinc-950 dark:text-white mb-4\">User Details</h3>\n <dl class=\"space-y-4 text-sm\">\n <div>\n <dt class=\"text-zinc-500 dark:text-zinc-400\">User ID</dt>\n <dd class=\"mt-1 text-zinc-950 dark:text-white font-mono text-xs\">${data.userToEdit.id}</dd>\n </div>\n <div>\n <dt class=\"text-zinc-500 dark:text-zinc-400\">Created</dt>\n <dd class=\"mt-1 text-zinc-950 dark:text-white\">${new Date(data.userToEdit.createdAt).toLocaleDateString()}</dd>\n </div>\n ${data.userToEdit.lastLoginAt ? `\n <div>\n <dt class=\"text-zinc-500 dark:text-zinc-400\">Last Login</dt>\n <dd class=\"mt-1 text-zinc-950 dark:text-white\">${new Date(data.userToEdit.lastLoginAt).toLocaleDateString()}</dd>\n </div>\n ` : ''}\n <div>\n <dt class=\"text-zinc-500 dark:text-zinc-400\">Status</dt>\n <dd class=\"mt-1\">\n ${data.userToEdit.isActive\n ? '<span class=\"inline-flex items-center px-2 py-0.5 rounded-md text-xs font-medium bg-lime-50 dark:bg-lime-500/10 text-lime-700 dark:text-lime-300 ring-1 ring-inset ring-lime-700/10 dark:ring-lime-400/20\">Active</span>'\n : '<span class=\"inline-flex items-center px-2 py-0.5 rounded-md text-xs font-medium bg-red-50 dark:bg-red-500/10 text-red-700 dark:text-red-400 ring-1 ring-inset ring-red-700/10 dark:ring-red-500/20\">Inactive</span>'\n }\n </dd>\n </div>\n ${data.userToEdit.twoFactorEnabled ? `\n <div>\n <dt class=\"text-zinc-500 dark:text-zinc-400\">Security</dt>\n <dd class=\"mt-1\">\n <span class=\"inline-flex items-center px-2 py-0.5 rounded-md text-xs font-medium bg-blue-50 dark:bg-blue-500/10 text-blue-700 dark:text-blue-400 ring-1 ring-inset ring-blue-700/10 dark:ring-blue-500/20\">2FA Enabled</span>\n </dd>\n </div>\n ` : ''}\n </dl>\n </div>\n\n <!-- Danger Zone -->\n <div class=\"rounded-xl bg-red-50 dark:bg-red-500/10 shadow-sm ring-1 ring-red-600/20 dark:ring-red-500/20 p-6\">\n <h3 class=\"text-base font-semibold text-red-900 dark:text-red-300 mb-2\">Danger Zone</h3>\n <p class=\"text-sm text-red-700 dark:text-red-400 mb-4\">Irreversible and destructive actions</p>\n\n <div class=\"flex gap-3 mb-4\">\n <div class=\"flex h-6 shrink-0 items-center\">\n <div class=\"group grid size-4 grid-cols-1\">\n <input\n type=\"checkbox\"\n id=\"hard-delete-checkbox\"\n class=\"col-start-1 row-start-1 appearance-none rounded border border-red-300 dark:border-red-700 bg-white dark:bg-red-950/50 checked:border-red-600 checked:bg-red-600 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-red-600 disabled:border-red-200 dark:disabled:border-red-900 disabled:bg-red-50 dark:disabled:bg-red-950/30 disabled:checked:bg-red-300 dark:disabled:checked:bg-red-900 forced-colors:appearance-auto\"\n />\n <svg viewBox=\"0 0 14 14\" fill=\"none\" class=\"pointer-events-none col-start-1 row-start-1 size-3.5 self-center justify-self-center stroke-white group-has-[:disabled]:stroke-red-950/25 dark:group-has-[:disabled]:stroke-white/25\">\n <path d=\"M3 8L6 11L11 3.5\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"opacity-0 group-has-[:checked]:opacity-100\" />\n <path d=\"M3 7H11\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"opacity-0 group-has-[:indeterminate]:opacity-100\" />\n </svg>\n </div>\n </div>\n <div class=\"text-sm/6\">\n <label for=\"hard-delete-checkbox\" class=\"font-medium text-red-900 dark:text-red-300 cursor-pointer\">Hard Delete (Permanent)</label>\n <p class=\"text-red-700 dark:text-red-400\">Permanently remove from database. Unchecked performs soft delete (deactivate only).</p>\n </div>\n </div>\n\n <button\n onclick=\"deleteUser('${data.userToEdit.id}')\"\n class=\"w-full inline-flex items-center justify-center rounded-lg bg-red-600 px-3 py-2 text-sm font-semibold text-white hover:bg-red-700 transition-colors\"\n >\n <svg class=\"-ml-0.5 mr-1.5 h-5 w-5\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16\"/>\n </svg>\n Delete User\n </button>\n </div>\n </div>\n </div>\n </div>\n\n <script>\n let userIdToDelete = null;\n\n function deleteUser(userId) {\n userIdToDelete = userId;\n showConfirmDialog('delete-user-confirm');\n }\n\n function performDeleteUser() {\n if (!userIdToDelete) return;\n\n const checkbox = document.getElementById('hard-delete-checkbox');\n const hardDelete = checkbox ? checkbox.checked : false;\n\n fetch(\\`/admin/users/\\${userIdToDelete}\\`, {\n method: 'DELETE',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({ hardDelete })\n })\n .then(response => response.json())\n .then(data => {\n if (data.success) {\n // Add a small delay to ensure database transaction completes\n // and add cache busting to force refresh\n setTimeout(() => {\n window.location.href = '/admin/users?_t=' + Date.now()\n }, 300)\n } else {\n alert('Error deleting user: ' + (data.error || 'Unknown error'))\n }\n })\n .catch(error => {\n console.error('Error:', error)\n alert('Error deleting user')\n })\n .finally(() => {\n userIdToDelete = null;\n });\n }\n </script>\n\n <!-- Confirmation Dialogs -->\n ${renderConfirmationDialog({\n id: 'delete-user-confirm',\n title: 'Delete User',\n message: 'Are you sure you want to delete this user? Check the \"Hard Delete\" option to permanently remove all data from the database. This action cannot be undone!',\n confirmText: 'Delete',\n cancelText: 'Cancel',\n iconColor: 'red',\n confirmClass: 'bg-red-500 hover:bg-red-400',\n onConfirm: 'performDeleteUser()'\n })}\n\n ${getConfirmationDialogScript()}\n `\n\n const layoutData: AdminLayoutCatalystData = {\n title: 'Edit User',\n pageTitle: `Edit User - ${data.userToEdit.firstName} ${data.userToEdit.lastName}`,\n currentPath: '/admin/users',\n user: data.user,\n content: pageContent\n }\n\n return renderAdminLayoutCatalyst(layoutData)\n}\n","export interface ConfirmationDialogOptions {\n id: string\n title: string\n message: string\n confirmText?: string\n cancelText?: string\n confirmClass?: string\n iconColor?: 'red' | 'yellow' | 'blue'\n onConfirm?: string // JavaScript code to execute on confirm\n}\n\nexport function renderConfirmationDialog(options: ConfirmationDialogOptions): string {\n const {\n id,\n title,\n message,\n confirmText = 'Confirm',\n cancelText = 'Cancel',\n confirmClass = 'bg-red-500 hover:bg-red-400',\n iconColor = 'red',\n onConfirm = ''\n } = options\n\n const iconColorClasses = {\n red: 'bg-red-500/10 text-red-400',\n yellow: 'bg-yellow-500/10 text-yellow-400',\n blue: 'bg-blue-500/10 text-blue-400'\n }\n\n return `\n <el-dialog>\n <dialog\n id=\"${id}\"\n aria-labelledby=\"${id}-title\"\n class=\"fixed inset-0 m-0 size-auto max-h-none max-w-none overflow-y-auto bg-transparent p-0 backdrop:bg-transparent\"\n >\n <el-dialog-backdrop class=\"fixed inset-0 bg-gray-900/50 transition-opacity data-[closed]:opacity-0 data-[enter]:duration-300 data-[leave]:duration-200 data-[enter]:ease-out data-[leave]:ease-in\"></el-dialog-backdrop>\n\n <div tabindex=\"0\" class=\"flex min-h-full items-end justify-center p-4 text-center focus:outline focus:outline-0 sm:items-center sm:p-0\">\n <el-dialog-panel class=\"relative transform overflow-hidden rounded-lg bg-gray-800 px-4 pb-4 pt-5 text-left shadow-xl outline outline-1 -outline-offset-1 outline-white/10 transition-all data-[closed]:translate-y-4 data-[closed]:opacity-0 data-[enter]:duration-300 data-[leave]:duration-200 data-[enter]:ease-out data-[leave]:ease-in sm:my-8 sm:w-full sm:max-w-lg sm:p-6 data-[closed]:sm:translate-y-0 data-[closed]:sm:scale-95\">\n <div class=\"sm:flex sm:items-start\">\n <div class=\"mx-auto flex size-12 shrink-0 items-center justify-center rounded-full ${iconColorClasses[iconColor]} sm:mx-0 sm:size-10\">\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\" data-slot=\"icon\" aria-hidden=\"true\" class=\"size-6\">\n <path d=\"M12 9v3.75m-9.303 3.376c-.866 1.5.217 3.374 1.948 3.374h14.71c1.73 0 2.813-1.874 1.948-3.374L13.949 3.378c-.866-1.5-3.032-1.5-3.898 0L2.697 16.126ZM12 15.75h.007v.008H12v-.008Z\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n </svg>\n </div>\n <div class=\"mt-3 text-center sm:ml-4 sm:mt-0 sm:text-left\">\n <h3 id=\"${id}-title\" class=\"text-base font-semibold text-white\">${title}</h3>\n <div class=\"mt-2\">\n <p class=\"text-sm text-gray-400\">${message}</p>\n </div>\n </div>\n </div>\n <div class=\"mt-5 sm:mt-4 sm:flex sm:flex-row-reverse\">\n <button\n type=\"button\"\n onclick=\"${onConfirm}; document.getElementById('${id}').close()\"\n command=\"close\"\n commandfor=\"${id}\"\n class=\"confirm-button inline-flex w-full justify-center rounded-md ${confirmClass} px-3 py-2 text-sm font-semibold text-white sm:ml-3 sm:w-auto\"\n >\n ${confirmText}\n </button>\n <button\n type=\"button\"\n command=\"close\"\n commandfor=\"${id}\"\n class=\"mt-3 inline-flex w-full justify-center rounded-md bg-white/10 px-3 py-2 text-sm font-semibold text-white ring-1 ring-inset ring-white/5 hover:bg-white/20 sm:mt-0 sm:w-auto\"\n >\n ${cancelText}\n </button>\n </div>\n </el-dialog-panel>\n </div>\n </dialog>\n </el-dialog>\n `\n}\n\n/**\n * Helper function to show a confirmation dialog programmatically\n * Usage in templates: Add this script and call showConfirmDialog()\n */\nexport function getConfirmationDialogScript(): string {\n return `\n <script src=\"https://cdn.jsdelivr.net/npm/@tailwindplus/elements@1\" type=\"module\"></script>\n <script>\n function showConfirmDialog(dialogId) {\n const dialog = document.getElementById(dialogId);\n if (dialog) {\n dialog.showModal();\n }\n }\n </script>\n `\n}\n","import { renderAdminLayoutCatalyst, AdminLayoutCatalystData } from '../layouts/admin-layout-catalyst.template'\nimport { renderAlert } from '../alert.template'\n\nexport interface UserNewPageData {\n roles: Array<{ value: string; label: string }>\n error?: string\n success?: string\n user?: {\n name: string\n email: string\n role: string\n }\n}\n\nexport function renderUserNewPage(data: UserNewPageData): string {\n const pageContent = `\n <div>\n <!-- Header -->\n <div class=\"flex flex-col sm:flex-row sm:items-center sm:justify-between mb-6\">\n <div>\n <div class=\"flex items-center gap-3 mb-2\">\n <a href=\"/admin/users\" class=\"text-zinc-500 dark:text-zinc-400 hover:text-zinc-950 dark:hover:text-white transition-colors\">\n <svg class=\"h-5 w-5\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M15 19l-7-7 7-7\"/>\n </svg>\n </a>\n <h1 class=\"text-2xl/8 font-semibold text-zinc-950 dark:text-white sm:text-xl/8\">Create New User</h1>\n </div>\n <p class=\"mt-2 text-sm/6 text-zinc-500 dark:text-zinc-400\">Add a new user account to the system</p>\n </div>\n <div class=\"mt-4 sm:mt-0 sm:ml-16 sm:flex-none flex space-x-3\">\n <button\n type=\"submit\"\n form=\"user-new-form\"\n class=\"inline-flex items-center justify-center rounded-lg bg-zinc-950 dark:bg-white px-3.5 py-2.5 text-sm font-semibold text-white dark:text-zinc-950 hover:bg-zinc-800 dark:hover:bg-zinc-100 transition-colors shadow-sm\"\n >\n <svg class=\"-ml-0.5 mr-1.5 h-5 w-5\" viewBox=\"0 0 20 20\" fill=\"currentColor\">\n <path d=\"M10.75 4.75a.75.75 0 00-1.5 0v4.5h-4.5a.75.75 0 000 1.5h4.5v4.5a.75.75 0 001.5 0v-4.5h4.5a.75.75 0 000-1.5h-4.5v-4.5z\" />\n </svg>\n Create User\n </button>\n <a\n href=\"/admin/users\"\n class=\"inline-flex items-center justify-center rounded-lg bg-white dark:bg-zinc-800 px-3.5 py-2.5 text-sm font-semibold text-zinc-950 dark:text-white ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 hover:bg-zinc-50 dark:hover:bg-zinc-700 transition-colors shadow-sm\"\n >\n Cancel\n </a>\n </div>\n </div>\n\n <!-- Alert Messages -->\n <div id=\"form-messages\">\n ${data.error ? renderAlert({ type: 'error', message: data.error, dismissible: true }) : ''}\n ${data.success ? renderAlert({ type: 'success', message: data.success, dismissible: true }) : ''}\n </div>\n\n <!-- User New Form -->\n <div class=\"grid grid-cols-1 lg:grid-cols-3 gap-6\">\n <!-- Main Form -->\n <div class=\"lg:col-span-2\">\n <div class=\"rounded-xl bg-white dark:bg-zinc-900 shadow-sm ring-1 ring-zinc-950/5 dark:ring-white/10 p-8\">\n <form id=\"user-new-form\" hx-post=\"/admin/users/new\" hx-target=\"#form-messages\">\n\n <!-- Basic Information -->\n <div class=\"mb-8\">\n <h3 class=\"text-base font-semibold text-zinc-950 dark:text-white mb-4\">Basic Information</h3>\n <div class=\"grid grid-cols-1 md:grid-cols-2 gap-6\">\n <div>\n <label class=\"block text-sm font-medium text-zinc-950 dark:text-white mb-2\">\n First Name <span class=\"text-red-500\">*</span>\n </label>\n <input\n type=\"text\"\n name=\"first_name\"\n required\n placeholder=\"Enter first name\"\n class=\"w-full rounded-lg bg-white dark:bg-zinc-800 px-3 py-2 text-sm text-zinc-950 dark:text-white shadow-sm ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 placeholder:text-zinc-400 dark:placeholder:text-zinc-500 focus:outline-none focus:ring-2 focus:ring-zinc-950 dark:focus:ring-white transition-shadow\"\n />\n </div>\n\n <div>\n <label class=\"block text-sm font-medium text-zinc-950 dark:text-white mb-2\">\n Last Name <span class=\"text-red-500\">*</span>\n </label>\n <input\n type=\"text\"\n name=\"last_name\"\n required\n placeholder=\"Enter last name\"\n class=\"w-full rounded-lg bg-white dark:bg-zinc-800 px-3 py-2 text-sm text-zinc-950 dark:text-white shadow-sm ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 placeholder:text-zinc-400 dark:placeholder:text-zinc-500 focus:outline-none focus:ring-2 focus:ring-zinc-950 dark:focus:ring-white transition-shadow\"\n />\n </div>\n\n <div>\n <label class=\"block text-sm font-medium text-zinc-950 dark:text-white mb-2\">\n Username <span class=\"text-red-500\">*</span>\n </label>\n <input\n type=\"text\"\n name=\"username\"\n required\n placeholder=\"Enter username\"\n class=\"w-full rounded-lg bg-white dark:bg-zinc-800 px-3 py-2 text-sm text-zinc-950 dark:text-white shadow-sm ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 placeholder:text-zinc-400 dark:placeholder:text-zinc-500 focus:outline-none focus:ring-2 focus:ring-zinc-950 dark:focus:ring-white transition-shadow\"\n />\n </div>\n\n <div>\n <label class=\"block text-sm font-medium text-zinc-950 dark:text-white mb-2\">\n Email <span class=\"text-red-500\">*</span>\n </label>\n <input\n type=\"email\"\n name=\"email\"\n required\n placeholder=\"user@example.com\"\n class=\"w-full rounded-lg bg-white dark:bg-zinc-800 px-3 py-2 text-sm text-zinc-950 dark:text-white shadow-sm ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 placeholder:text-zinc-400 dark:placeholder:text-zinc-500 focus:outline-none focus:ring-2 focus:ring-zinc-950 dark:focus:ring-white transition-shadow\"\n />\n </div>\n\n <div>\n <label class=\"block text-sm font-medium text-zinc-950 dark:text-white mb-2\">Phone</label>\n <input\n type=\"tel\"\n name=\"phone\"\n placeholder=\"+1 (555) 000-0000\"\n class=\"w-full rounded-lg bg-white dark:bg-zinc-800 px-3 py-2 text-sm text-zinc-950 dark:text-white shadow-sm ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 placeholder:text-zinc-400 dark:placeholder:text-zinc-500 focus:outline-none focus:ring-2 focus:ring-zinc-950 dark:focus:ring-white transition-shadow\"\n />\n </div>\n\n <div>\n <label for=\"role\" class=\"block text-sm/6 font-medium text-zinc-950 dark:text-white\">\n Role <span class=\"text-red-500\">*</span>\n </label>\n <div class=\"mt-2 grid grid-cols-1\">\n <select\n id=\"role\"\n name=\"role\"\n required\n class=\"col-start-1 row-start-1 w-full appearance-none rounded-md bg-white/5 dark:bg-white/5 py-1.5 pl-3 pr-8 text-base text-zinc-950 dark:text-white outline outline-1 -outline-offset-1 outline-zinc-500/30 dark:outline-zinc-400/30 *:bg-white dark:*:bg-zinc-800 focus-visible:outline focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-zinc-500 dark:focus-visible:outline-zinc-400 sm:text-sm/6\"\n >\n ${data.roles.map(role => `\n <option value=\"${role.value}\">${role.label}</option>\n `).join('')}\n </select>\n <svg viewBox=\"0 0 16 16\" fill=\"currentColor\" data-slot=\"icon\" aria-hidden=\"true\" class=\"pointer-events-none col-start-1 row-start-1 mr-2 size-5 self-center justify-self-end text-zinc-600 dark:text-zinc-400 sm:size-4\">\n <path d=\"M4.22 6.22a.75.75 0 0 1 1.06 0L8 8.94l2.72-2.72a.75.75 0 1 1 1.06 1.06l-3.25 3.25a.75.75 0 0 1-1.06 0L4.22 7.28a.75.75 0 0 1 0-1.06Z\" clip-rule=\"evenodd\" fill-rule=\"evenodd\" />\n </svg>\n </div>\n </div>\n </div>\n\n <div class=\"mt-6\">\n <label class=\"block text-sm font-medium text-zinc-950 dark:text-white mb-2\">Bio</label>\n <textarea\n name=\"bio\"\n rows=\"3\"\n placeholder=\"Enter a short bio (optional)\"\n class=\"w-full rounded-lg bg-white dark:bg-zinc-800 px-3 py-2 text-sm text-zinc-950 dark:text-white shadow-sm ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 placeholder:text-zinc-400 dark:placeholder:text-zinc-500 focus:outline-none focus:ring-2 focus:ring-zinc-950 dark:focus:ring-white transition-shadow\"\n ></textarea>\n </div>\n </div>\n\n <!-- Password -->\n <div class=\"mb-8\">\n <h3 class=\"text-base font-semibold text-zinc-950 dark:text-white mb-4\">Password</h3>\n <div class=\"grid grid-cols-1 md:grid-cols-2 gap-6\">\n <div>\n <label class=\"block text-sm font-medium text-zinc-950 dark:text-white mb-2\">\n Password <span class=\"text-red-500\">*</span>\n </label>\n <input\n type=\"password\"\n name=\"password\"\n required\n placeholder=\"Enter password (min 8 characters)\"\n minlength=\"8\"\n class=\"w-full rounded-lg bg-white dark:bg-zinc-800 px-3 py-2 text-sm text-zinc-950 dark:text-white shadow-sm ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 placeholder:text-zinc-400 dark:placeholder:text-zinc-500 focus:outline-none focus:ring-2 focus:ring-zinc-950 dark:focus:ring-white transition-shadow\"\n />\n </div>\n\n <div>\n <label class=\"block text-sm font-medium text-zinc-950 dark:text-white mb-2\">\n Confirm Password <span class=\"text-red-500\">*</span>\n </label>\n <input\n type=\"password\"\n name=\"confirm_password\"\n required\n placeholder=\"Confirm password\"\n minlength=\"8\"\n class=\"w-full rounded-lg bg-white dark:bg-zinc-800 px-3 py-2 text-sm text-zinc-950 dark:text-white shadow-sm ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 placeholder:text-zinc-400 dark:placeholder:text-zinc-500 focus:outline-none focus:ring-2 focus:ring-zinc-950 dark:focus:ring-white transition-shadow\"\n />\n </div>\n </div>\n </div>\n\n <!-- Account Status -->\n <div class=\"mb-8\">\n <h3 class=\"text-base font-semibold text-zinc-950 dark:text-white mb-4\">Account Status</h3>\n <div class=\"space-y-5\">\n <div class=\"flex gap-3\">\n <div class=\"flex h-6 shrink-0 items-center\">\n <div class=\"group grid size-4 grid-cols-1\">\n <input\n type=\"checkbox\"\n id=\"is_active\"\n name=\"is_active\"\n value=\"1\"\n checked\n class=\"col-start-1 row-start-1 appearance-none rounded border border-zinc-950/10 dark:border-white/10 bg-white dark:bg-white/5 checked:border-indigo-500 checked:bg-indigo-500 indeterminate:border-indigo-500 indeterminate:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-500 disabled:border-zinc-950/5 dark:disabled:border-white/5 disabled:bg-zinc-950/10 dark:disabled:bg-white/10 disabled:checked:bg-zinc-950/10 dark:disabled:checked:bg-white/10 forced-colors:appearance-auto\"\n />\n <svg viewBox=\"0 0 14 14\" fill=\"none\" class=\"pointer-events-none col-start-1 row-start-1 size-3.5 self-center justify-self-center stroke-white group-has-[:disabled]:stroke-zinc-950/25 dark:group-has-[:disabled]:stroke-white/25\">\n <path d=\"M3 8L6 11L11 3.5\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"opacity-0 group-has-[:checked]:opacity-100\" />\n <path d=\"M3 7H11\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"opacity-0 group-has-[:indeterminate]:opacity-100\" />\n </svg>\n </div>\n </div>\n <div class=\"text-sm/6\">\n <label for=\"is_active\" class=\"font-medium text-zinc-950 dark:text-white\">Account Active</label>\n <p class=\"text-zinc-500 dark:text-zinc-400\">User can sign in and access the system</p>\n </div>\n </div>\n\n <div class=\"flex gap-3\">\n <div class=\"flex h-6 shrink-0 items-center\">\n <div class=\"group grid size-4 grid-cols-1\">\n <input\n type=\"checkbox\"\n id=\"email_verified\"\n name=\"email_verified\"\n value=\"1\"\n class=\"col-start-1 row-start-1 appearance-none rounded border border-zinc-950/10 dark:border-white/10 bg-white dark:bg-white/5 checked:border-indigo-500 checked:bg-indigo-500 indeterminate:border-indigo-500 indeterminate:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-500 disabled:border-zinc-950/5 dark:disabled:border-white/5 disabled:bg-zinc-950/10 dark:disabled:bg-white/10 disabled:checked:bg-zinc-950/10 dark:disabled:checked:bg-white/10 forced-colors:appearance-auto\"\n />\n <svg viewBox=\"0 0 14 14\" fill=\"none\" class=\"pointer-events-none col-start-1 row-start-1 size-3.5 self-center justify-self-center stroke-white group-has-[:disabled]:stroke-zinc-950/25 dark:group-has-[:disabled]:stroke-white/25\">\n <path d=\"M3 8L6 11L11 3.5\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"opacity-0 group-has-[:checked]:opacity-100\" />\n <path d=\"M3 7H11\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"opacity-0 group-has-[:indeterminate]:opacity-100\" />\n </svg>\n </div>\n </div>\n <div class=\"text-sm/6\">\n <label for=\"email_verified\" class=\"font-medium text-zinc-950 dark:text-white\">Email Verified</label>\n <p class=\"text-zinc-500 dark:text-zinc-400\">Mark email as verified</p>\n </div>\n </div>\n </div>\n </div>\n\n </form>\n </div>\n </div>\n\n <!-- Sidebar -->\n <div class=\"lg:col-span-1\">\n <!-- Help Text -->\n <div class=\"rounded-xl bg-blue-50 dark:bg-blue-500/10 shadow-sm ring-1 ring-blue-600/20 dark:ring-blue-500/20 p-6\">\n <h3 class=\"text-base font-semibold text-blue-900 dark:text-blue-300 mb-2\">Creating a User</h3>\n <div class=\"text-sm text-blue-700 dark:text-blue-400 space-y-3\">\n <p>Fill in the required fields marked with <span class=\"text-red-500\">*</span> to create a new user account.</p>\n <p>The password must be at least 8 characters long.</p>\n <p>By default, new users are created as active and can sign in immediately.</p>\n <p>You can edit user details and permissions after creation.</p>\n </div>\n </div>\n\n <!-- Role Descriptions -->\n <div class=\"rounded-xl bg-white dark:bg-zinc-900 shadow-sm ring-1 ring-zinc-950/5 dark:ring-white/10 p-6 mt-6\">\n <h3 class=\"text-base font-semibold text-zinc-950 dark:text-white mb-4\">Role Descriptions</h3>\n <dl class=\"space-y-3 text-sm\">\n <div>\n <dt class=\"font-medium text-zinc-950 dark:text-white\">Administrator</dt>\n <dd class=\"text-zinc-500 dark:text-zinc-400\">Full system access and permissions</dd>\n </div>\n <div>\n <dt class=\"font-medium text-zinc-950 dark:text-white\">Editor</dt>\n <dd class=\"text-zinc-500 dark:text-zinc-400\">Can create and edit content</dd>\n </div>\n <div>\n <dt class=\"font-medium text-zinc-950 dark:text-white\">Author</dt>\n <dd class=\"text-zinc-500 dark:text-zinc-400\">Can create own content</dd>\n </div>\n <div>\n <dt class=\"font-medium text-zinc-950 dark:text-white\">Viewer</dt>\n <dd class=\"text-zinc-500 dark:text-zinc-400\">Read-only access</dd>\n </div>\n </dl>\n </div>\n </div>\n </div>\n </div>\n `\n\n const layoutData: AdminLayoutCatalystData = {\n title: 'Create User',\n pageTitle: 'Create New User',\n currentPath: '/admin/users',\n user: data.user,\n content: pageContent\n }\n\n return renderAdminLayoutCatalyst(layoutData)\n}\n","import { renderAdminLayoutCatalyst, AdminLayoutCatalystData } from '../layouts/admin-layout-catalyst.template'\nimport { renderPagination, PaginationData } from '../pagination.template'\nimport { renderAlert } from '../alert.template'\nimport { renderTable, TableColumn, TableData } from '../table.template'\nimport { renderConfirmationDialog, getConfirmationDialogScript } from '../components/confirmation-dialog.template'\n\nexport interface User {\n id: string\n email: string\n username: string\n firstName: string\n lastName: string\n role: string\n avatar?: string\n isActive: boolean\n lastLoginAt?: number\n createdAt: number\n updatedAt: number\n formattedLastLogin?: string\n formattedCreatedAt?: string\n}\n\nexport interface UsersListPageData {\n users: User[]\n pagination?: PaginationData\n currentPage: number\n totalPages: number\n totalUsers: number\n statusFilter?: string\n roleFilter?: string\n searchFilter?: string\n error?: string\n success?: string\n user?: {\n name: string\n email: string\n role: string\n }\n version?: string\n}\n\nexport function renderUsersListPage(data: UsersListPageData): string {\n const columns: TableColumn[] = [\n {\n key: 'avatar',\n label: '',\n className: 'w-12',\n sortable: false,\n render: (value: string | null, row: User) => {\n const initials = `${row.firstName.charAt(0)}${row.lastName.charAt(0)}`.toUpperCase()\n if (value) {\n return `<img src=\"${value}\" alt=\"${row.firstName} ${row.lastName}\" class=\"w-8 h-8 rounded-full\">`\n }\n return `\n <div class=\"w-8 h-8 bg-gradient-to-br from-cyan-400 to-blue-500 dark:from-cyan-300 dark:to-blue-400 rounded-full flex items-center justify-center\">\n <span class=\"text-xs font-medium text-white\">${initials}</span>\n </div>\n `\n }\n },\n {\n key: 'name',\n label: 'Name',\n sortable: true,\n sortType: 'string',\n render: (_value: any, row: User) => {\n const escapeHtml = (text: string) => text.replace(/[&<>\"']/g, (char) => ({\n '&': '&',\n '<': '<',\n '>': '>',\n '\"': '"',\n \"'\": '''\n }[char] || char))\n \n const truncatedFirstName = row.firstName.length > 25 ? row.firstName.substring(0, 25) + '...' : row.firstName\n const truncatedLastName = row.lastName.length > 25 ? row.lastName.substring(0, 25) + '...' : row.lastName\n const fullName = escapeHtml(`${truncatedFirstName} ${truncatedLastName}`)\n const truncatedUsername = row.username.length > 100 ? row.username.substring(0, 100) + '...' : row.username\n const username = escapeHtml(truncatedUsername)\n const statusBadge = row.isActive ?\n '<span class=\"inline-flex items-center px-2 py-0.5 rounded-md text-xs font-medium bg-lime-50 dark:bg-lime-500/10 text-lime-700 dark:text-lime-300 ring-1 ring-inset ring-lime-700/10 dark:ring-lime-400/20 ml-2\">Active</span>' :\n '<span class=\"inline-flex items-center px-2 py-0.5 rounded-md text-xs font-medium bg-red-50 dark:bg-red-500/10 text-red-700 dark:text-red-400 ring-1 ring-inset ring-red-700/10 dark:ring-red-500/20 ml-2\">Inactive</span>'\n return `\n <div>\n <div class=\"text-sm font-medium text-zinc-950 dark:text-white\">${fullName}${statusBadge}</div>\n <div class=\"text-sm text-zinc-500 dark:text-zinc-400\">@${username}</div>\n </div>\n `\n }\n },\n {\n key: 'email',\n label: 'Email',\n sortable: true,\n sortType: 'string',\n render: (value: string) => {\n const escapeHtml = (text: string) => text.replace(/[&<>\"']/g, (char) => ({\n '&': '&',\n '<': '<',\n '>': '>',\n '\"': '"',\n \"'\": '''\n }[char] || char))\n const escapedEmail = escapeHtml(value)\n return `<a href=\"mailto:${escapedEmail}\" class=\"text-cyan-600 dark:text-cyan-400 hover:text-cyan-700 dark:hover:text-cyan-300 transition-colors\">${escapedEmail}</a>`\n }\n },\n {\n key: 'role',\n label: 'Role',\n sortable: true,\n sortType: 'string',\n render: (value: string) => {\n const roleColors = {\n admin: 'bg-red-50 dark:bg-red-500/10 text-red-700 dark:text-red-400 ring-1 ring-inset ring-red-700/10 dark:ring-red-500/20',\n editor: 'bg-blue-50 dark:bg-blue-500/10 text-blue-700 dark:text-blue-400 ring-1 ring-inset ring-blue-700/10 dark:ring-blue-500/20',\n author: 'bg-cyan-50 dark:bg-cyan-500/10 text-cyan-700 dark:text-cyan-400 ring-1 ring-inset ring-cyan-700/10 dark:ring-cyan-500/20',\n viewer: 'bg-zinc-50 dark:bg-zinc-800 text-zinc-600 dark:text-zinc-400 ring-1 ring-inset ring-zinc-500/10 dark:ring-zinc-400/20'\n }\n const colorClass = roleColors[value as keyof typeof roleColors] || 'bg-zinc-50 dark:bg-zinc-800 text-zinc-600 dark:text-zinc-400 ring-1 ring-inset ring-zinc-500/10 dark:ring-zinc-400/20'\n return `<span class=\"inline-flex items-center px-2 py-0.5 rounded-md text-xs font-medium ${colorClass}\">${value.charAt(0).toUpperCase() + value.slice(1)}</span>`\n }\n },\n {\n key: 'lastLoginAt',\n label: 'Last Login',\n sortable: true,\n sortType: 'date',\n render: (value: number | null) => {\n if (!value) return '<span class=\"text-zinc-500 dark:text-zinc-400\">Never</span>'\n return `<span class=\"text-sm text-zinc-500 dark:text-zinc-400\">${new Date(value).toLocaleDateString()}</span>`\n }\n },\n {\n key: 'createdAt',\n label: 'Created',\n sortable: true,\n sortType: 'date',\n render: (value: number) => `<span class=\"text-sm text-zinc-500 dark:text-zinc-400\">${new Date(value).toLocaleDateString()}</span>`\n },\n {\n key: 'actions',\n label: 'Actions',\n className: 'text-right',\n sortable: false,\n render: (_value: any, row: User) => `\n <div class=\"flex justify-end space-x-2\">\n ${row.isActive ?\n `<button onclick=\"toggleUserStatus('${row.id}', false)\" title=\"Deactivate user\" class=\"inline-flex items-center justify-center p-2 text-sm font-medium rounded-lg bg-gradient-to-r from-red-500 to-pink-500 dark:from-red-400 dark:to-pink-400 text-white hover:from-red-600 hover:to-pink-600 dark:hover:from-red-500 dark:hover:to-pink-500 shadow-sm transition-all duration-200\">\n <svg class=\"h-4 w-4\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M18.364 18.364A9 9 0 005.636 5.636m12.728 12.728A9 9 0 015.636 5.636m12.728 12.728L5.636 5.636\"/>\n </svg>\n </button>` :\n `<button onclick=\"toggleUserStatus('${row.id}', true)\" title=\"Activate user\" class=\"inline-flex items-center justify-center p-2 text-sm font-medium rounded-lg bg-gradient-to-r from-lime-500 to-green-500 dark:from-lime-400 dark:to-green-400 text-white hover:from-lime-600 hover:to-green-600 dark:hover:from-lime-500 dark:hover:to-green-500 shadow-sm transition-all duration-200\">\n <svg class=\"h-4 w-4\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z\"/>\n </svg>\n </button>`\n }\n </div>\n `\n }\n ]\n\n const tableData: TableData<User> = {\n tableId: 'users-table',\n columns,\n rows: data.users,\n selectable: false,\n rowClickable: true,\n rowClickUrl: (row: User) => `/admin/users/${row.id}/edit`,\n emptyMessage: 'No users found'\n }\n\n const pageContent = `\n <div>\n <!-- Header -->\n <div class=\"flex flex-col sm:flex-row sm:items-center sm:justify-between mb-6\">\n <div>\n <h1 class=\"text-2xl/8 font-semibold text-zinc-950 dark:text-white sm:text-xl/8\">User Management</h1>\n <p class=\"mt-2 text-sm/6 text-zinc-500 dark:text-zinc-400\">Manage user accounts and permissions</p>\n </div>\n <div class=\"mt-4 sm:mt-0 sm:ml-16 sm:flex-none flex space-x-3\">\n <a href=\"/admin/users/new\" class=\"inline-flex items-center justify-center rounded-lg bg-zinc-950 dark:bg-white px-3.5 py-2.5 text-sm font-semibold text-white dark:text-zinc-950 hover:bg-zinc-800 dark:hover:bg-zinc-100 transition-colors shadow-sm\">\n <svg class=\"-ml-0.5 mr-1.5 h-5 w-5\" viewBox=\"0 0 20 20\" fill=\"currentColor\">\n <path d=\"M10.75 4.75a.75.75 0 00-1.5 0v4.5h-4.5a.75.75 0 000 1.5h4.5v4.5a.75.75 0 001.5 0v-4.5h4.5a.75.75 0 000-1.5h-4.5v-4.5z\" />\n </svg>\n Add User\n </a>\n <button class=\"inline-flex items-center justify-center rounded-lg bg-white dark:bg-zinc-800 px-3.5 py-2.5 text-sm font-semibold text-zinc-950 dark:text-white ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 hover:bg-zinc-50 dark:hover:bg-zinc-700 transition-colors shadow-sm\" onclick=\"exportUsers()\">\n <svg class=\"-ml-0.5 mr-1.5 h-5 w-5\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M12 10v6m0 0l-3-3m3 3l3-3m2 8H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z\"></path>\n </svg>\n Export\n </button>\n </div>\n </div>\n\n <!-- Alert Messages -->\n ${data.error ? renderAlert({ type: 'error', message: data.error, dismissible: true }) : ''}\n ${data.success ? renderAlert({ type: 'success', message: data.success, dismissible: true }) : ''}\n\n <!-- Stats -->\n <div class=\"mb-6\">\n <h3 class=\"text-base font-semibold text-zinc-950 dark:text-white\">User Statistics</h3>\n <dl class=\"mt-5 grid grid-cols-1 divide-zinc-950/5 dark:divide-white/10 overflow-hidden rounded-lg bg-zinc-800/75 dark:bg-zinc-800/75 ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 md:grid-cols-4 md:divide-x md:divide-y-0\">\n <div class=\"px-4 py-5 sm:p-6\">\n <dt class=\"text-base font-normal text-zinc-700 dark:text-zinc-100\">Total Users</dt>\n <dd class=\"mt-1 flex items-baseline justify-between md:block lg:flex\">\n <div class=\"flex items-baseline text-2xl font-semibold text-cyan-400\">\n ${data.totalUsers}\n </div>\n <div class=\"inline-flex items-baseline rounded-full bg-lime-400/10 text-lime-600 dark:text-lime-400 px-2.5 py-0.5 text-sm font-medium md:mt-2 lg:mt-0\">\n <svg viewBox=\"0 0 20 20\" fill=\"currentColor\" class=\"-ml-1 mr-0.5 size-5 shrink-0 self-center\">\n <path d=\"M10 17a.75.75 0 0 1-.75-.75V5.612L5.29 9.77a.75.75 0 0 1-1.08-1.04l5.25-5.5a.75.75 0 0 1 1.08 0l5.25 5.5a.75.75 0 1 1-1.08 1.04l-3.96-4.158V16.25A.75.75 0 0 1 10 17Z\" clip-rule=\"evenodd\" fill-rule=\"evenodd\" />\n </svg>\n <span class=\"sr-only\">Increased by</span>\n 5.2%\n </div>\n </dd>\n </div>\n <div class=\"px-4 py-5 sm:p-6\">\n <dt class=\"text-base font-normal text-zinc-700 dark:text-zinc-100\">Active Users</dt>\n <dd class=\"mt-1 flex items-baseline justify-between md:block lg:flex\">\n <div class=\"flex items-baseline text-2xl font-semibold text-lime-400\">\n ${data.users.filter(u => u.isActive).length}\n </div>\n <div class=\"inline-flex items-baseline rounded-full bg-lime-400/10 text-lime-600 dark:text-lime-400 px-2.5 py-0.5 text-sm font-medium md:mt-2 lg:mt-0\">\n <svg viewBox=\"0 0 20 20\" fill=\"currentColor\" class=\"-ml-1 mr-0.5 size-5 shrink-0 self-center\">\n <path d=\"M10 17a.75.75 0 0 1-.75-.75V5.612L5.29 9.77a.75.75 0 0 1-1.08-1.04l5.25-5.5a.75.75 0 0 1 1.08 0l5.25 5.5a.75.75 0 1 1-1.08 1.04l-3.96-4.158V16.25A.75.75 0 0 1 10 17Z\" clip-rule=\"evenodd\" fill-rule=\"evenodd\" />\n </svg>\n <span class=\"sr-only\">Increased by</span>\n 3.1%\n </div>\n </dd>\n </div>\n <div class=\"px-4 py-5 sm:p-6\">\n <dt class=\"text-base font-normal text-zinc-700 dark:text-zinc-100\">Administrators</dt>\n <dd class=\"mt-1 flex items-baseline justify-between md:block lg:flex\">\n <div class=\"flex items-baseline text-2xl font-semibold text-pink-400\">\n ${data.users.filter(u => u.role === 'admin').length}\n </div>\n <div class=\"inline-flex items-baseline rounded-full bg-lime-400/10 text-lime-600 dark:text-lime-400 px-2.5 py-0.5 text-sm font-medium md:mt-2 lg:mt-0\">\n <svg viewBox=\"0 0 20 20\" fill=\"currentColor\" class=\"-ml-1 mr-0.5 size-5 shrink-0 self-center\">\n <path d=\"M10 17a.75.75 0 0 1-.75-.75V5.612L5.29 9.77a.75.75 0 0 1-1.08-1.04l5.25-5.5a.75.75 0 0 1 1.08 0l5.25 5.5a.75.75 0 1 1-1.08 1.04l-3.96-4.158V16.25A.75.75 0 0 1 10 17Z\" clip-rule=\"evenodd\" fill-rule=\"evenodd\" />\n </svg>\n <span class=\"sr-only\">Increased by</span>\n 1.8%\n </div>\n </dd>\n </div>\n <div class=\"px-4 py-5 sm:p-6\">\n <dt class=\"text-base font-normal text-zinc-700 dark:text-zinc-100\">Active This Week</dt>\n <dd class=\"mt-1 flex items-baseline justify-between md:block lg:flex\">\n <div class=\"flex items-baseline text-2xl font-semibold text-purple-400\">\n ${data.users.filter(u => u.lastLoginAt && u.lastLoginAt > Date.now() - 7 * 24 * 60 * 60 * 1000).length}\n </div>\n <div class=\"inline-flex items-baseline rounded-full bg-pink-400/10 text-pink-600 dark:text-pink-400 px-2.5 py-0.5 text-sm font-medium md:mt-2 lg:mt-0\">\n <svg viewBox=\"0 0 20 20\" fill=\"currentColor\" class=\"-ml-1 mr-0.5 size-5 shrink-0 self-center\">\n <path d=\"M10 3a.75.75 0 0 1 .75.75v10.638l3.96-4.158a.75.75 0 1 1 1.08 1.04l-5.25 5.5a.75.75 0 0 1-1.08 0l-5.25-5.5a.75.75 0 1 1 1.08-1.04l3.96 4.158V3.75A.75.75 0 0 1 10 3Z\" clip-rule=\"evenodd\" fill-rule=\"evenodd\" />\n </svg>\n <span class=\"sr-only\">Decreased by</span>\n 2.3%\n </div>\n </dd>\n </div>\n </dl>\n </div>\n\n <!-- Filters with Gradient Background -->\n <div class=\"relative rounded-xl overflow-hidden mb-6\">\n <!-- Gradient Background Layer -->\n <div class=\"absolute inset-0 bg-gradient-to-r from-purple-500/10 via-pink-500/10 to-blue-500/10 dark:from-purple-400/20 dark:via-pink-400/20 dark:to-blue-400/20\"></div>\n\n <!-- Content Layer with backdrop blur -->\n <div class=\"relative bg-white/80 dark:bg-zinc-900/80 backdrop-blur-xl shadow-sm ring-1 ring-zinc-950/5 dark:ring-white/10\">\n <div class=\"px-6 py-5\">\n <div class=\"grid grid-cols-1 md:grid-cols-4 gap-4\">\n <!-- Modern Search Input -->\n <div>\n <label class=\"block text-sm font-medium text-zinc-950 dark:text-white mb-2\">Search</label>\n <div class=\"relative group\">\n <input\n type=\"text\"\n name=\"search\"\n id=\"user-search-input\"\n value=\"${data.searchFilter || ''}\"\n placeholder=\"Search users...\"\n class=\"rounded-full bg-white/90 dark:bg-zinc-800/90 backdrop-blur-sm px-4 py-2.5 pl-11 text-sm w-full text-zinc-950 dark:text-white border-2 border-purple-200/50 dark:border-purple-700/50 placeholder:text-zinc-400 dark:placeholder:text-zinc-500 focus:outline-none focus:border-purple-500 dark:focus:border-purple-400 focus:bg-white dark:focus:bg-zinc-800 focus:shadow-lg focus:shadow-purple-500/20 dark:focus:shadow-purple-400/20 transition-all duration-300\"\n hx-get=\"/admin/users\"\n hx-trigger=\"keyup changed delay:300ms\"\n hx-target=\"body\"\n hx-include=\"[name='role'], [name='status']\"\n hx-on::after-request=\"\n const input = document.getElementById('user-search-input');\n if (input && document.activeElement === input) {\n const len = input.value.length;\n setTimeout(() => {\n input.focus();\n input.setSelectionRange(len, len);\n }, 10);\n }\n \"\n >\n <!-- Gradient search icon -->\n <div class=\"absolute left-3.5 top-2.5 flex items-center justify-center w-5 h-5 rounded-full bg-gradient-to-br from-purple-400 to-pink-500 dark:from-purple-300 dark:to-pink-400 opacity-90 group-focus-within:opacity-100 transition-opacity\">\n <svg class=\"h-3 w-3 text-white\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\" stroke-width=\"2.5\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z\"/>\n </svg>\n </div>\n </div>\n </div>\n\n <div>\n <label class=\"block text-sm/6 font-medium text-zinc-950 dark:text-white\">Role</label>\n <div class=\"mt-2 grid grid-cols-1\">\n <select\n name=\"role\"\n hx-get=\"/admin/users\"\n hx-trigger=\"change\"\n hx-target=\"body\"\n hx-include=\"[name='search'], [name='status']\"\n class=\"col-start-1 row-start-1 w-full appearance-none rounded-md bg-white/5 dark:bg-white/5 py-1.5 pl-3 pr-8 text-base text-zinc-950 dark:text-white outline outline-1 -outline-offset-1 outline-purple-500/30 dark:outline-purple-400/30 *:bg-white dark:*:bg-zinc-800 focus-visible:outline focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-purple-500 dark:focus-visible:outline-purple-400 sm:text-sm/6\"\n >\n <option value=\"\" ${!data.roleFilter ? 'selected' : ''}>All Roles</option>\n <option value=\"admin\" ${data.roleFilter === 'admin' ? 'selected' : ''}>Admin</option>\n <option value=\"editor\" ${data.roleFilter === 'editor' ? 'selected' : ''}>Editor</option>\n <option value=\"author\" ${data.roleFilter === 'author' ? 'selected' : ''}>Author</option>\n <option value=\"viewer\" ${data.roleFilter === 'viewer' ? 'selected' : ''}>Viewer</option>\n </select>\n <svg viewBox=\"0 0 16 16\" fill=\"currentColor\" data-slot=\"icon\" aria-hidden=\"true\" class=\"pointer-events-none col-start-1 row-start-1 mr-2 size-5 self-center justify-self-end text-purple-600 dark:text-purple-400 sm:size-4\">\n <path d=\"M4.22 6.22a.75.75 0 0 1 1.06 0L8 8.94l2.72-2.72a.75.75 0 1 1 1.06 1.06l-3.25 3.25a.75.75 0 0 1-1.06 0L4.22 7.28a.75.75 0 0 1 0-1.06Z\" clip-rule=\"evenodd\" fill-rule=\"evenodd\" />\n </svg>\n </div>\n </div>\n\n <div>\n <label class=\"block text-sm/6 font-medium text-zinc-950 dark:text-white\">Status</label>\n <div class=\"mt-2 grid grid-cols-1\">\n <select\n name=\"status\"\n hx-get=\"/admin/users\"\n hx-trigger=\"change\"\n hx-target=\"body\"\n hx-include=\"[name='search'], [name='role']\"\n class=\"col-start-1 row-start-1 w-full appearance-none rounded-md bg-white/5 dark:bg-white/5 py-1.5 pl-3 pr-8 text-base text-zinc-950 dark:text-white outline outline-1 -outline-offset-1 outline-purple-500/30 dark:outline-purple-400/30 *:bg-white dark:*:bg-zinc-800 focus-visible:outline focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-purple-500 dark:focus-visible:outline-purple-400 sm:text-sm/6\"\n >\n <option value=\"active\" ${!data.statusFilter || data.statusFilter === 'active' ? 'selected' : ''}>Active</option>\n <option value=\"inactive\" ${data.statusFilter === 'inactive' ? 'selected' : ''}>Inactive</option>\n <option value=\"all\" ${data.statusFilter === 'all' ? 'selected' : ''}>All Users</option>\n </select>\n <svg viewBox=\"0 0 16 16\" fill=\"currentColor\" data-slot=\"icon\" aria-hidden=\"true\" class=\"pointer-events-none col-start-1 row-start-1 mr-2 size-5 self-center justify-self-end text-purple-600 dark:text-purple-400 sm:size-4\">\n <path d=\"M4.22 6.22a.75.75 0 0 1 1.06 0L8 8.94l2.72-2.72a.75.75 0 1 1 1.06 1.06l-3.25 3.25a.75.75 0 0 1-1.06 0L4.22 7.28a.75.75 0 0 1 0-1.06Z\" clip-rule=\"evenodd\" fill-rule=\"evenodd\" />\n </svg>\n </div>\n </div>\n\n <div>\n <label class=\"block text-sm/6 font-medium text-zinc-950 dark:text-white\"> </label>\n <div class=\"mt-2\">\n <button\n class=\"inline-flex items-center gap-x-1.5 justify-center px-4 py-2 bg-white/90 dark:bg-zinc-800/90 backdrop-blur-sm text-zinc-950 dark:text-white text-sm font-medium rounded-full ring-1 ring-inset ring-purple-200/50 dark:ring-purple-700/50 hover:bg-gradient-to-r hover:from-purple-50 hover:to-pink-50 dark:hover:from-purple-900/30 dark:hover:to-pink-900/30 hover:ring-purple-300 dark:hover:ring-purple-600 transition-all duration-200 w-full\"\n onclick=\"clearFilters()\"\n >\n <svg class=\"h-4 w-4\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M6 18L18 6M6 6l12 12\"/>\n </svg>\n Clear Filters\n </button>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n\n <!-- Users Table -->\n ${renderTable(tableData)}\n\n <!-- Pagination -->\n ${data.pagination ? renderPagination(data.pagination) : ''}\n </div>\n\n <script>\n let userStatusData = null;\n\n function toggleUserStatus(userId, activate) {\n userStatusData = { userId, activate };\n showConfirmDialog('toggle-user-status-confirm');\n }\n\n function performToggleUserStatus() {\n if (!userStatusData) return;\n\n const { userId, activate } = userStatusData;\n\n fetch(\\`/admin/users/\\${userId}/toggle\\`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({ active: activate })\n })\n .then(response => response.json())\n .then(data => {\n if (data.success) {\n location.reload()\n } else {\n alert('Error updating user status')\n }\n })\n .catch(error => {\n console.error('Error:', error)\n alert('Error updating user status')\n })\n .finally(() => {\n userStatusData = null;\n });\n }\n\n function clearFilters() {\n window.location.href = '/admin/users'\n }\n\n function exportUsers() {\n window.open('/admin/users/export', '_blank')\n }\n </script>\n\n <!-- Confirmation Dialogs -->\n ${renderConfirmationDialog({\n id: 'toggle-user-status-confirm',\n title: 'Toggle User Status',\n message: 'Are you sure you want to activate/deactivate this user?',\n confirmText: 'Confirm',\n cancelText: 'Cancel',\n iconColor: 'yellow',\n confirmClass: 'bg-yellow-500 hover:bg-yellow-400',\n onConfirm: 'performToggleUserStatus()'\n })}\n\n ${getConfirmationDialogScript()}\n `\n\n const layoutData: AdminLayoutCatalystData = {\n title: 'Users',\n pageTitle: 'User Management',\n currentPath: '/admin/users',\n user: data.user,\n version: data.version,\n content: pageContent\n }\n\n return renderAdminLayoutCatalyst(layoutData)\n} ","import { Hono } from 'hono'\nimport { requireAuth, logActivity, AuthManager } from '../middleware'\nimport { sanitizeInput } from '../utils/sanitize'\nimport { renderProfilePage, renderAvatarImage, type UserProfile, type ProfilePageData } from '../templates/pages/admin-profile.template'\nimport { renderAlert } from '../templates/components/alert.template'\nimport { renderActivityLogsPage, type ActivityLogsPageData, type ActivityLog } from '../templates/pages/admin-activity-logs.template'\nimport { renderUserEditPage, type UserEditPageData, type UserEditData } from '../templates/pages/admin-user-edit.template'\nimport { renderUserNewPage, type UserNewPageData } from '../templates/pages/admin-user-new.template'\nimport { renderUsersListPage, type UsersListPageData, type User } from '../templates/pages/admin-users-list.template'\nimport type { Bindings, Variables } from '../app'\n\nconst userRoutes = new Hono<{ Bindings: Bindings; Variables: Variables }>()\n\n// Apply authentication middleware to all routes\nuserRoutes.use('*', requireAuth())\n\n// Redirect /admin to /admin/dashboard\nuserRoutes.get('/', (c) => {\n return c.redirect('/admin/dashboard')\n})\n\n// Timezone options for profile form\nconst TIMEZONES = [\n { value: 'UTC', label: 'UTC' },\n { value: 'America/New_York', label: 'Eastern Time' },\n { value: 'America/Chicago', label: 'Central Time' },\n { value: 'America/Denver', label: 'Mountain Time' },\n { value: 'America/Los_Angeles', label: 'Pacific Time' },\n { value: 'Europe/London', label: 'London' },\n { value: 'Europe/Paris', label: 'Paris' },\n { value: 'Europe/Berlin', label: 'Berlin' },\n { value: 'Asia/Tokyo', label: 'Tokyo' },\n { value: 'Asia/Shanghai', label: 'Shanghai' },\n { value: 'Australia/Sydney', label: 'Sydney' }\n]\n\n// Language options for profile form\nconst LANGUAGES = [\n { value: 'en', label: 'English' },\n { value: 'es', label: 'Spanish' },\n { value: 'fr', label: 'French' },\n { value: 'de', label: 'German' },\n { value: 'it', label: 'Italian' },\n { value: 'pt', label: 'Portuguese' },\n { value: 'ja', label: 'Japanese' },\n { value: 'ko', label: 'Korean' },\n { value: 'zh', label: 'Chinese' }\n]\n\n// Role options for user form\nconst ROLES = [\n { value: 'admin', label: 'Administrator' },\n { value: 'editor', label: 'Editor' },\n { value: 'author', label: 'Author' },\n { value: 'viewer', label: 'Viewer' }\n]\n\n/**\n * GET /admin/profile - Show user profile page\n */\nuserRoutes.get('/profile', async (c) => {\n const user = c.get('user')\n const db = c.env.DB\n\n try {\n // Get user profile data\n const userStmt = db.prepare(`\n SELECT id, email, username, first_name, last_name, phone, bio, avatar_url,\n timezone, language, theme, email_notifications, two_factor_enabled,\n role, created_at, last_login_at\n FROM users \n WHERE id = ? AND is_active = 1\n `)\n \n const userProfile = await userStmt.bind(user!.userId).first() as any\n\n if (!userProfile) {\n return c.json({ error: 'User not found' }, 404)\n }\n\n // Convert to UserProfile interface\n const profile: UserProfile = {\n id: userProfile.id,\n email: userProfile.email,\n username: userProfile.username || '',\n first_name: userProfile.first_name || '',\n last_name: userProfile.last_name || '',\n phone: userProfile.phone,\n bio: userProfile.bio,\n avatar_url: userProfile.avatar_url,\n timezone: userProfile.timezone || 'UTC',\n language: userProfile.language || 'en',\n theme: userProfile.theme || 'dark',\n email_notifications: Boolean(userProfile.email_notifications),\n two_factor_enabled: Boolean(userProfile.two_factor_enabled),\n role: userProfile.role,\n created_at: userProfile.created_at,\n last_login_at: userProfile.last_login_at\n }\n\n const pageData: ProfilePageData = {\n profile,\n timezones: TIMEZONES,\n languages: LANGUAGES,\n user: {\n name: `${profile.first_name} ${profile.last_name}`.trim() || profile.username || user!.email,\n email: user!.email,\n role: user!.role\n }\n }\n\n return c.html(renderProfilePage(pageData))\n } catch (error) {\n console.error('Profile page error:', error)\n \n const pageData: ProfilePageData = {\n profile: {} as UserProfile,\n timezones: TIMEZONES,\n languages: LANGUAGES,\n error: 'Failed to load profile. Please try again.',\n user: {\n name: user!.email,\n email: user!.email,\n role: user!.role\n }\n }\n\n return c.html(renderProfilePage(pageData))\n }\n})\n\n/**\n * PUT /admin/profile - Update user profile\n */\nuserRoutes.put('/profile', async (c) => {\n const user = c.get('user')\n const db = c.env.DB\n\n try {\n const formData = await c.req.formData()\n\n // Sanitize all user inputs to prevent XSS attacks\n const firstName = sanitizeInput(formData.get('first_name')?.toString())\n const lastName = sanitizeInput(formData.get('last_name')?.toString())\n const username = sanitizeInput(formData.get('username')?.toString())\n const email = formData.get('email')?.toString()?.trim().toLowerCase() || ''\n const phone = sanitizeInput(formData.get('phone')?.toString()) || null\n const bio = sanitizeInput(formData.get('bio')?.toString()) || null\n const timezone = formData.get('timezone')?.toString() || 'UTC'\n const language = formData.get('language')?.toString() || 'en'\n const emailNotifications = formData.get('email_notifications') === '1'\n\n // Validate required fields\n if (!firstName || !lastName || !username || !email) {\n return c.html(renderAlert({\n type: 'error',\n message: 'First name, last name, username, and email are required.',\n dismissible: true\n }))\n }\n\n // Validate email format\n const emailRegex = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/\n if (!emailRegex.test(email)) {\n return c.html(renderAlert({ \n type: 'error', \n message: 'Please enter a valid email address.',\n dismissible: true \n }))\n }\n\n // Check if username/email are taken by another user\n const checkStmt = db.prepare(`\n SELECT id FROM users \n WHERE (username = ? OR email = ?) AND id != ? AND is_active = 1\n `)\n const existingUser = await checkStmt.bind(username, email, user!.userId).first()\n\n if (existingUser) {\n return c.html(renderAlert({ \n type: 'error', \n message: 'Username or email is already taken by another user!.',\n dismissible: true \n }))\n }\n\n // Update user profile\n const updateStmt = db.prepare(`\n UPDATE users SET \n first_name = ?, last_name = ?, username = ?, email = ?,\n phone = ?, bio = ?, timezone = ?, language = ?,\n email_notifications = ?, updated_at = ?\n WHERE id = ?\n `)\n\n await updateStmt.bind(\n firstName, lastName, username, email,\n phone, bio, timezone, language,\n emailNotifications ? 1 : 0, Date.now(),\n user!.userId\n ).run()\n\n // Log the activity\n await logActivity(\n db, user!.userId, 'profile.update', 'users', user!.userId,\n { fields: ['first_name', 'last_name', 'username', 'email', 'phone', 'bio', 'timezone', 'language', 'email_notifications'] },\n c.req.header('x-forwarded-for') || c.req.header('cf-connecting-ip'),\n c.req.header('user-agent')\n )\n\n return c.html(renderAlert({ \n type: 'success', \n message: 'Profile updated successfully!',\n dismissible: true \n }))\n\n } catch (error) {\n console.error('Profile update error:', error)\n return c.html(renderAlert({ \n type: 'error', \n message: 'Failed to update profile. Please try again.',\n dismissible: true \n }))\n }\n})\n\n/**\n * POST /admin/profile/avatar - Upload user avatar\n */\nuserRoutes.post('/profile/avatar', async (c) => {\n const user = c.get('user')\n const db = c.env.DB\n\n try {\n const formData = await c.req.formData()\n const avatarFile = formData.get('avatar') as File | null\n\n if (!avatarFile || typeof avatarFile === 'string' || !avatarFile.name) {\n return c.html(renderAlert({\n type: 'error',\n message: 'Please select an image file.',\n dismissible: true\n }))\n }\n\n // Validate file type\n const allowedTypes = ['image/jpeg', 'image/png', 'image/gif', 'image/webp']\n if (!allowedTypes.includes(avatarFile.type)) {\n return c.html(renderAlert({ \n type: 'error', \n message: 'Please upload a valid image file (JPEG, PNG, GIF, or WebP).',\n dismissible: true \n }))\n }\n\n // Validate file size (5MB max)\n const maxSize = 5 * 1024 * 1024\n if (avatarFile.size > maxSize) {\n return c.html(renderAlert({ \n type: 'error', \n message: 'Image file must be smaller than 5MB.',\n dismissible: true \n }))\n }\n\n // For now, we'll simulate storing the avatar\n // In a real implementation, you'd upload to cloud storage (R2, S3, etc.)\n const avatarUrl = `/uploads/avatars/${user!.userId}-${Date.now()}.${avatarFile.type.split('/')[1]}`\n\n // Update user avatar URL in database\n const updateStmt = db.prepare(`\n UPDATE users SET avatar_url = ?, updated_at = ?\n WHERE id = ?\n `)\n\n await updateStmt.bind(avatarUrl, Date.now(), user!.userId).run()\n\n // Get updated user data to render the avatar\n const userStmt = db.prepare(`\n SELECT first_name, last_name FROM users WHERE id = ?\n `)\n const userData = await userStmt.bind(user!.userId).first() as any\n\n // Log the activity\n await logActivity(\n db, user!.userId, 'profile.avatar_update', 'users', user!.userId,\n { avatar_url: avatarUrl },\n c.req.header('x-forwarded-for') || c.req.header('cf-connecting-ip'),\n c.req.header('user-agent')\n )\n\n // Return both the alert message and the updated avatar image using HTMX out-of-band swap\n const alertHtml = renderAlert({\n type: 'success',\n message: 'Profile picture updated successfully!',\n dismissible: true\n })\n\n // Add timestamp to avatar URL to bust cache\n const avatarUrlWithCache = `${avatarUrl}?t=${Date.now()}`\n const avatarImageHtml = renderAvatarImage(avatarUrlWithCache, userData.first_name, userData.last_name)\n\n // Use hx-swap-oob to update the avatar image container\n const avatarImageWithOob = avatarImageHtml.replace(\n 'id=\"avatar-image-container\"',\n 'id=\"avatar-image-container\" hx-swap-oob=\"true\"'\n )\n\n return c.html(alertHtml + avatarImageWithOob)\n\n } catch (error) {\n console.error('Avatar upload error:', error)\n return c.html(renderAlert({ \n type: 'error', \n message: 'Failed to upload profile picture. Please try again.',\n dismissible: true \n }))\n }\n})\n\n/**\n * POST /admin/profile/password - Change user password\n */\nuserRoutes.post('/profile/password', async (c) => {\n const user = c.get('user')\n const db = c.env.DB\n\n try {\n const formData = await c.req.formData()\n \n const currentPassword = formData.get('current_password')?.toString() || ''\n const newPassword = formData.get('new_password')?.toString() || ''\n const confirmPassword = formData.get('confirm_password')?.toString() || ''\n\n // Validate input\n if (!currentPassword || !newPassword || !confirmPassword) {\n return c.html(renderAlert({ \n type: 'error', \n message: 'All password fields are required.',\n dismissible: true \n }))\n }\n\n if (newPassword !== confirmPassword) {\n return c.html(renderAlert({ \n type: 'error', \n message: 'New passwords do not match.',\n dismissible: true \n }))\n }\n\n if (newPassword.length < 8) {\n return c.html(renderAlert({ \n type: 'error', \n message: 'New password must be at least 8 characters long.',\n dismissible: true \n }))\n }\n\n // Get current user data\n const userStmt = db.prepare(`\n SELECT password_hash FROM users WHERE id = ? AND is_active = 1\n `)\n const userData = await userStmt.bind(user!.userId).first() as any\n\n if (!userData) {\n return c.html(renderAlert({ \n type: 'error', \n message: 'User not found.',\n dismissible: true \n }))\n }\n\n // Verify current password\n const validPassword = await AuthManager.verifyPassword(currentPassword, userData.password_hash)\n if (!validPassword) {\n return c.html(renderAlert({ \n type: 'error', \n message: 'Current password is incorrect.',\n dismissible: true \n }))\n }\n\n // Hash new password\n const newPasswordHash = await AuthManager.hashPassword(newPassword)\n\n // Store old password in history\n const historyStmt = db.prepare(`\n INSERT INTO password_history (id, user_id, password_hash, created_at)\n VALUES (?, ?, ?, ?)\n `)\n await historyStmt.bind(\n crypto.randomUUID(),\n user!.userId,\n userData.password_hash,\n Date.now()\n ).run()\n\n // Update user password\n const updateStmt = db.prepare(`\n UPDATE users SET password_hash = ?, updated_at = ?\n WHERE id = ?\n `)\n await updateStmt.bind(newPasswordHash, Date.now(), user!.userId).run()\n\n // Log the activity\n await logActivity(\n db, user!.userId, 'profile.password_change', 'users', user!.userId,\n null,\n c.req.header('x-forwarded-for') || c.req.header('cf-connecting-ip'),\n c.req.header('user-agent')\n )\n\n return c.html(renderAlert({ \n type: 'success', \n message: 'Password updated successfully!',\n dismissible: true \n }))\n\n } catch (error) {\n console.error('Password change error:', error)\n return c.html(renderAlert({ \n type: 'error', \n message: 'Failed to update password. Please try again.',\n dismissible: true \n }))\n }\n})\n\n/**\n * GET /admin/users - List all users\n * Returns HTML for browser requests and JSON for API requests\n * Note: Already protected by requireAuth() and requireRole(['admin', 'editor'])\n */\nuserRoutes.get('/users', async (c) => {\n const db = c.env.DB\n const user = c.get('user')\n\n try {\n // Get pagination parameters\n const page = parseInt(c.req.query('page') || '1')\n const limit = parseInt(c.req.query('limit') || '20')\n const search = c.req.query('search') || ''\n const roleFilter = c.req.query('role') || ''\n const statusFilter = c.req.query('status') || 'active'\n const offset = (page - 1) * limit\n\n // Build search query\n let whereClause = ''\n let params: any[] = []\n\n // Handle status filter\n if (statusFilter === 'active') {\n whereClause = 'WHERE u.is_active = 1'\n } else if (statusFilter === 'inactive') {\n whereClause = 'WHERE u.is_active = 0'\n } else {\n // 'all' - no filter\n whereClause = 'WHERE 1=1'\n }\n\n if (search) {\n whereClause += ' AND (u.first_name LIKE ? OR u.last_name LIKE ? OR u.email LIKE ? OR u.username LIKE ?)'\n const searchParam = `%${search}%`\n params.push(searchParam, searchParam, searchParam, searchParam)\n }\n\n if (roleFilter) {\n whereClause += ' AND u.role = ?'\n params.push(roleFilter)\n }\n\n // Get users\n const usersStmt = db.prepare(`\n SELECT u.id, u.email, u.username, u.first_name, u.last_name,\n u.role, u.avatar_url, u.created_at, u.last_login_at, u.updated_at,\n u.email_verified, u.two_factor_enabled, u.is_active\n FROM users u\n ${whereClause}\n ORDER BY u.created_at DESC\n LIMIT ? OFFSET ?\n `)\n\n const { results: usersData } = await usersStmt.bind(...params, limit, offset).all()\n\n // Get total count\n const countStmt = db.prepare(`\n SELECT COUNT(*) as total FROM users u ${whereClause}\n `)\n const countResult = await countStmt.bind(...params).first() as any\n const totalUsers = countResult?.total || 0\n\n // Log the activity\n await logActivity(\n db, user!.userId, 'users.list_view', 'users', undefined,\n { search, page, limit },\n c.req.header('x-forwarded-for') || c.req.header('cf-connecting-ip'),\n c.req.header('user-agent')\n )\n\n // Check if this is an API request (accept header contains 'application/json')\n const acceptHeader = c.req.header('accept') || ''\n const isApiRequest = acceptHeader.includes('application/json')\n\n if (isApiRequest) {\n // Return JSON for API requests\n return c.json({\n users: usersData || [],\n pagination: {\n page,\n limit,\n total: totalUsers,\n pages: Math.ceil(totalUsers / limit)\n }\n })\n }\n\n // Return HTML for browser requests\n const users: User[] = (usersData || []).map((u: any) => ({\n id: u.id,\n email: u.email,\n username: u.username || '',\n firstName: u.first_name || '',\n lastName: u.last_name || '',\n role: u.role,\n avatar: u.avatar_url,\n isActive: Boolean(u.is_active),\n lastLoginAt: u.last_login_at,\n createdAt: u.created_at,\n updatedAt: u.updated_at,\n formattedLastLogin: u.last_login_at ? new Date(u.last_login_at).toLocaleDateString() : undefined,\n formattedCreatedAt: new Date(u.created_at).toLocaleDateString()\n }))\n\n const pageData: UsersListPageData = {\n users,\n currentPage: page,\n totalPages: Math.ceil(totalUsers / limit),\n totalUsers,\n searchFilter: search,\n roleFilter,\n statusFilter,\n pagination: {\n currentPage: page,\n totalPages: Math.ceil(totalUsers / limit),\n totalItems: totalUsers,\n itemsPerPage: limit,\n startItem: offset + 1,\n endItem: Math.min(offset + limit, totalUsers),\n baseUrl: '/admin/users'\n },\n user: {\n name: user!.email.split('@')[0] || user!.email,\n email: user!.email,\n role: user!.role\n }\n }\n\n return c.html(renderUsersListPage(pageData))\n\n } catch (error) {\n console.error('Users list error:', error)\n\n const acceptHeader = c.req.header('accept') || ''\n const isApiRequest = acceptHeader.includes('application/json')\n\n if (isApiRequest) {\n return c.json({ error: 'Failed to load users' }, 500)\n }\n\n return c.html(renderAlert({\n type: 'error',\n message: 'Failed to load users. Please try again.',\n dismissible: true\n }), 500)\n }\n})\n\n/**\n * GET /admin/users/new - Show new user creation page\n */\nuserRoutes.get('/users/new', async (c) => {\n const user = c.get('user')\n\n try {\n const pageData: UserNewPageData = {\n roles: ROLES,\n user: {\n name: user!.email.split('@')[0] || user!.email,\n email: user!.email,\n role: user!.role\n }\n }\n\n return c.html(renderUserNewPage(pageData))\n } catch (error) {\n console.error('User new page error:', error)\n\n return c.html(renderAlert({\n type: 'error',\n message: 'Failed to load user creation page. Please try again.',\n dismissible: true\n }), 500)\n }\n})\n\n/**\n * POST /admin/users/new - Create new user\n */\nuserRoutes.post('/users/new', async (c) => {\n const db = c.env.DB\n const user = c.get('user')\n\n try {\n const formData = await c.req.formData()\n\n // Sanitize all user inputs to prevent XSS attacks\n const firstName = sanitizeInput(formData.get('first_name')?.toString())\n const lastName = sanitizeInput(formData.get('last_name')?.toString())\n const username = sanitizeInput(formData.get('username')?.toString())\n const email = formData.get('email')?.toString()?.trim().toLowerCase() || ''\n const phone = sanitizeInput(formData.get('phone')?.toString()) || null\n const bio = sanitizeInput(formData.get('bio')?.toString()) || null\n const role = formData.get('role')?.toString() || 'viewer'\n const password = formData.get('password')?.toString() || ''\n const confirmPassword = formData.get('confirm_password')?.toString() || ''\n const isActive = formData.get('is_active') === '1'\n const emailVerified = formData.get('email_verified') === '1'\n\n // Validate required fields\n if (!firstName || !lastName || !username || !email || !password) {\n return c.html(renderAlert({\n type: 'error',\n message: 'First name, last name, username, email, and password are required.',\n dismissible: true\n }))\n }\n\n // Validate email format\n const emailRegex = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/\n if (!emailRegex.test(email)) {\n return c.html(renderAlert({\n type: 'error',\n message: 'Please enter a valid email address.',\n dismissible: true\n }))\n }\n\n // Validate password\n if (password.length < 8) {\n return c.html(renderAlert({\n type: 'error',\n message: 'Password must be at least 8 characters long.',\n dismissible: true\n }))\n }\n\n if (password !== confirmPassword) {\n return c.html(renderAlert({\n type: 'error',\n message: 'Passwords do not match.',\n dismissible: true\n }))\n }\n\n // Check if username/email are already taken\n const checkStmt = db.prepare(`\n SELECT id FROM users\n WHERE username = ? OR email = ?\n `)\n const existingUser = await checkStmt.bind(username, email).first()\n\n if (existingUser) {\n return c.html(renderAlert({\n type: 'error',\n message: 'Username or email is already taken.',\n dismissible: true\n }))\n }\n\n // Hash password\n const passwordHash = await AuthManager.hashPassword(password)\n\n // Create user\n const userId = crypto.randomUUID()\n const createStmt = db.prepare(`\n INSERT INTO users (\n id, email, username, first_name, last_name, phone, bio,\n password_hash, role, is_active, email_verified, created_at, updated_at\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n `)\n\n await createStmt.bind(\n userId, email, username, firstName, lastName, phone, bio,\n passwordHash, role, isActive ? 1 : 0, emailVerified ? 1 : 0,\n Date.now(), Date.now()\n ).run()\n\n // Log the activity\n await logActivity(\n db, user!.userId, 'user!.create', 'users', userId,\n { email, username, role },\n c.req.header('x-forwarded-for') || c.req.header('cf-connecting-ip'),\n c.req.header('user-agent')\n )\n\n // Redirect to user edit page\n return c.redirect(`/admin/users/${userId}/edit?success=User created successfully`)\n\n } catch (error) {\n console.error('User creation error:', error)\n return c.html(renderAlert({\n type: 'error',\n message: 'Failed to create user!. Please try again.',\n dismissible: true\n }))\n }\n})\n\n/**\n * GET /admin/users/:id - Get user by ID\n * Note: This endpoint returns users regardless of is_active status for admin purposes\n */\nuserRoutes.get('/users/:id', async (c) => {\n // Check if this is actually the edit route\n if (c.req.path.endsWith('/edit')) {\n return c.notFound()\n }\n\n const db = c.env.DB\n const user = c.get('user')\n const userId = c.req.param('id')\n\n try {\n // Get user data (including inactive users for admin access)\n const userStmt = db.prepare(`\n SELECT id, email, username, first_name, last_name, phone, bio, avatar_url,\n role, is_active, email_verified, two_factor_enabled, created_at, last_login_at\n FROM users\n WHERE id = ?\n `)\n\n const userRecord = await userStmt.bind(userId).first() as any\n\n if (!userRecord) {\n return c.json({ error: 'User not found' }, 404)\n }\n\n // Log the activity\n await logActivity(\n db, user!.userId, 'user!.view', 'users', userId,\n null,\n c.req.header('x-forwarded-for') || c.req.header('cf-connecting-ip'),\n c.req.header('user-agent')\n )\n\n return c.json({\n user: {\n id: userRecord.id,\n email: userRecord.email,\n username: userRecord.username,\n first_name: userRecord.first_name,\n last_name: userRecord.last_name,\n phone: userRecord.phone,\n bio: userRecord.bio,\n avatar_url: userRecord.avatar_url,\n role: userRecord.role,\n is_active: userRecord.is_active,\n email_verified: userRecord.email_verified,\n two_factor_enabled: userRecord.two_factor_enabled,\n created_at: userRecord.created_at,\n last_login_at: userRecord.last_login_at\n }\n })\n\n } catch (error) {\n console.error('User fetch error:', error)\n return c.json({ error: 'Failed to fetch user' }, 500)\n }\n})\n\n/**\n * GET /admin/users/:id/edit - Show user edit page\n */\nuserRoutes.get('/users/:id/edit', async (c) => {\n const db = c.env.DB\n const user = c.get('user')\n const userId = c.req.param('id')\n\n try {\n // Get user data\n const userStmt = db.prepare(`\n SELECT id, email, username, first_name, last_name, phone, bio, avatar_url,\n role, is_active, email_verified, two_factor_enabled, created_at, last_login_at\n FROM users\n WHERE id = ?\n `)\n\n const userToEdit = await userStmt.bind(userId).first() as any\n\n if (!userToEdit) {\n return c.html(renderAlert({\n type: 'error',\n message: 'User not found',\n dismissible: true\n }), 404)\n }\n\n // Convert to UserEditData interface\n const editData: UserEditData = {\n id: userToEdit.id,\n email: userToEdit.email,\n username: userToEdit.username || '',\n firstName: userToEdit.first_name || '',\n lastName: userToEdit.last_name || '',\n phone: userToEdit.phone,\n bio: userToEdit.bio,\n avatarUrl: userToEdit.avatar_url,\n role: userToEdit.role,\n isActive: Boolean(userToEdit.is_active),\n emailVerified: Boolean(userToEdit.email_verified),\n twoFactorEnabled: Boolean(userToEdit.two_factor_enabled),\n createdAt: userToEdit.created_at,\n lastLoginAt: userToEdit.last_login_at\n }\n\n const pageData: UserEditPageData = {\n userToEdit: editData,\n roles: ROLES,\n user: {\n name: user!.email.split('@')[0] || user!.email,\n email: user!.email,\n role: user!.role\n }\n }\n\n return c.html(renderUserEditPage(pageData))\n } catch (error) {\n console.error('User edit page error:', error)\n\n return c.html(renderAlert({\n type: 'error',\n message: 'Failed to load user!. Please try again.',\n dismissible: true\n }), 500)\n }\n})\n\n/**\n * PUT /admin/users/:id - Update user\n */\nuserRoutes.put('/users/:id', async (c) => {\n const db = c.env.DB\n const user = c.get('user')\n const userId = c.req.param('id')\n\n try {\n const formData = await c.req.formData()\n\n // Sanitize all user inputs to prevent XSS attacks\n const firstName = sanitizeInput(formData.get('first_name')?.toString())\n const lastName = sanitizeInput(formData.get('last_name')?.toString())\n const username = sanitizeInput(formData.get('username')?.toString())\n const email = formData.get('email')?.toString()?.trim().toLowerCase() || ''\n const phone = sanitizeInput(formData.get('phone')?.toString()) || null\n const bio = sanitizeInput(formData.get('bio')?.toString()) || null\n const role = formData.get('role')?.toString() || 'viewer'\n const isActive = formData.get('is_active') === '1'\n const emailVerified = formData.get('email_verified') === '1'\n\n // Validate required fields\n if (!firstName || !lastName || !username || !email) {\n return c.html(renderAlert({\n type: 'error',\n message: 'First name, last name, username, and email are required.',\n dismissible: true\n }))\n }\n\n // Validate email format\n const emailRegex = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/\n if (!emailRegex.test(email)) {\n return c.html(renderAlert({\n type: 'error',\n message: 'Please enter a valid email address.',\n dismissible: true\n }))\n }\n\n // Check if username/email are taken by another user\n const checkStmt = db.prepare(`\n SELECT id FROM users\n WHERE (username = ? OR email = ?) AND id != ?\n `)\n const existingUser = await checkStmt.bind(username, email, userId).first()\n\n if (existingUser) {\n return c.html(renderAlert({\n type: 'error',\n message: 'Username or email is already taken by another user!.',\n dismissible: true\n }))\n }\n\n // Update user\n const updateStmt = db.prepare(`\n UPDATE users SET\n first_name = ?, last_name = ?, username = ?, email = ?,\n phone = ?, bio = ?, role = ?, is_active = ?, email_verified = ?,\n updated_at = ?\n WHERE id = ?\n `)\n\n await updateStmt.bind(\n firstName, lastName, username, email,\n phone, bio, role, isActive ? 1 : 0, emailVerified ? 1 : 0,\n Date.now(), userId\n ).run()\n\n // Log the activity\n await logActivity(\n db, user!.userId, 'user!.update', 'users', userId,\n { fields: ['first_name', 'last_name', 'username', 'email', 'phone', 'bio', 'role', 'is_active', 'email_verified'] },\n c.req.header('x-forwarded-for') || c.req.header('cf-connecting-ip'),\n c.req.header('user-agent')\n )\n\n return c.html(renderAlert({\n type: 'success',\n message: 'User updated successfully!',\n dismissible: true\n }))\n\n } catch (error) {\n console.error('User update error:', error)\n return c.html(renderAlert({\n type: 'error',\n message: 'Failed to update user!. Please try again.',\n dismissible: true\n }))\n }\n})\n\n/**\n * POST /admin/users/:id/toggle - Toggle user active status\n */\nuserRoutes.post('/users/:id/toggle', async (c) => {\n const db = c.env.DB\n const user = c.get('user')\n const userId = c.req.param('id')\n\n try {\n const body = await c.req.json().catch(() => ({ active: true }))\n const active = body.active === true\n\n // Prevent self-deactivation\n if (userId === user!.userId && !active) {\n return c.json({ error: 'You cannot deactivate your own account' }, 400)\n }\n\n // Check if user exists\n const userStmt = db.prepare(`\n SELECT id, email FROM users WHERE id = ?\n `)\n const userToToggle = await userStmt.bind(userId).first() as any\n\n if (!userToToggle) {\n return c.json({ error: 'User not found' }, 404)\n }\n\n // Toggle user status\n const toggleStmt = db.prepare(`\n UPDATE users SET is_active = ?, updated_at = ? WHERE id = ?\n `)\n await toggleStmt.bind(active ? 1 : 0, Date.now(), userId).run()\n\n // Log the activity\n await logActivity(\n db, user!.userId, active ? 'user.activate' : 'user.deactivate', 'users', userId,\n { email: userToToggle.email },\n c.req.header('x-forwarded-for') || c.req.header('cf-connecting-ip'),\n c.req.header('user-agent')\n )\n\n return c.json({\n success: true,\n message: active ? 'User activated successfully' : 'User deactivated successfully'\n })\n\n } catch (error) {\n console.error('User toggle error:', error)\n return c.json({ error: 'Failed to toggle user status' }, 500)\n }\n})\n\n/**\n * DELETE /admin/users/:id - Delete user\n */\nuserRoutes.delete('/users/:id', async (c) => {\n const db = c.env.DB\n const user = c.get('user')\n const userId = c.req.param('id')\n\n try {\n // Get request body to check for hard delete option\n const body = await c.req.json().catch(() => ({ hardDelete: false }))\n const hardDelete = body.hardDelete === true\n\n // Prevent self-deletion\n if (userId === user!.userId) {\n return c.json({ error: 'You cannot delete your own account' }, 400)\n }\n\n // Check if user exists\n const userStmt = db.prepare(`\n SELECT id, email FROM users WHERE id = ?\n `)\n const userToDelete = await userStmt.bind(userId).first() as any\n\n if (!userToDelete) {\n return c.json({ error: 'User not found' }, 404)\n }\n\n if (hardDelete) {\n // Hard delete - permanently remove from database\n const deleteStmt = db.prepare(`\n DELETE FROM users WHERE id = ?\n `)\n await deleteStmt.bind(userId).run()\n\n // Log the activity\n await logActivity(\n db, user!.userId, 'user!.hard_delete', 'users', userId,\n { email: userToDelete.email, permanent: true },\n c.req.header('x-forwarded-for') || c.req.header('cf-connecting-ip'),\n c.req.header('user-agent')\n )\n\n return c.json({\n success: true,\n message: 'User permanently deleted'\n })\n } else {\n // Soft delete - deactivate by setting is_active = 0\n const deleteStmt = db.prepare(`\n UPDATE users SET is_active = 0, updated_at = ? WHERE id = ?\n `)\n await deleteStmt.bind(Date.now(), userId).run()\n\n // Log the activity\n await logActivity(\n db, user!.userId, 'user!.soft_delete', 'users', userId,\n { email: userToDelete.email },\n c.req.header('x-forwarded-for') || c.req.header('cf-connecting-ip'),\n c.req.header('user-agent')\n )\n\n return c.json({\n success: true,\n message: 'User deactivated successfully'\n })\n }\n\n } catch (error) {\n console.error('User deletion error:', error)\n return c.json({ error: 'Failed to delete user' }, 500)\n }\n})\n\n/**\n * POST /admin/invite-user - Invite a new user\n */\nuserRoutes.post('/invite-user', async (c) => {\n const db = c.env.DB\n const user = c.get('user')\n\n try {\n const formData = await c.req.formData()\n\n // Sanitize all user inputs to prevent XSS attacks\n const email = formData.get('email')?.toString()?.trim().toLowerCase() || ''\n const role = formData.get('role')?.toString()?.trim() || 'viewer'\n const firstName = sanitizeInput(formData.get('first_name')?.toString())\n const lastName = sanitizeInput(formData.get('last_name')?.toString())\n\n // Validate input\n if (!email || !firstName || !lastName) {\n return c.json({ error: 'Email, first name, and last name are required' }, 400)\n }\n\n // Validate email format\n const emailRegex = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/\n if (!emailRegex.test(email)) {\n return c.json({ error: 'Please enter a valid email address' }, 400)\n }\n\n // Check if user already exists\n const existingUserStmt = db.prepare(`\n SELECT id FROM users WHERE email = ?\n `)\n const existingUser = await existingUserStmt.bind(email).first()\n\n if (existingUser) {\n return c.json({ error: 'A user with this email already exists' }, 400)\n }\n\n // Generate invitation token\n const invitationToken = crypto.randomUUID()\n // const invitationExpires = Date.now() + (7 * 24 * 60 * 60 * 1000) // 7 days\n\n // Create user record with invitation\n const userId = crypto.randomUUID()\n const createUserStmt = db.prepare(`\n INSERT INTO users (\n id, email, first_name, last_name, role, \n invitation_token, invited_by, invited_at,\n is_active, email_verified, created_at, updated_at\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n `)\n\n await createUserStmt.bind(\n userId, email, firstName, lastName, role,\n invitationToken, user!.userId, Date.now(),\n 0, 0, Date.now(), Date.now()\n ).run()\n\n // Log the activity\n await logActivity(\n db, user!.userId, 'user!.invite_sent', 'users', userId,\n { email, role, invited_user_id: userId },\n c.req.header('x-forwarded-for') || c.req.header('cf-connecting-ip'),\n c.req.header('user-agent')\n )\n\n // In a real implementation, you would send an email here\n // For now, we'll return the invitation link\n const invitationLink = `${c.req.header('origin') || 'http://localhost:8787'}/auth/accept-invitation?token=${invitationToken}`\n\n return c.json({\n success: true,\n message: 'User invitation sent successfully',\n user: {\n id: userId,\n email,\n first_name: firstName,\n last_name: lastName,\n role\n },\n invitation_link: invitationLink // In production, this would be sent via email\n })\n\n } catch (error) {\n console.error('User invitation error:', error)\n return c.json({ error: 'Failed to send user invitation' }, 500)\n }\n})\n\n/**\n * POST /admin/resend-invitation/:id - Resend invitation\n */\nuserRoutes.post('/resend-invitation/:id', async (c) => {\n const db = c.env.DB\n const user = c.get('user')\n const userId = c.req.param('id')\n\n try {\n // Check if user exists and is invited but not active\n const userStmt = db.prepare(`\n SELECT id, email, first_name, last_name, role, invitation_token\n FROM users \n WHERE id = ? AND is_active = 0 AND invitation_token IS NOT NULL\n `)\n const invitedUser = await userStmt.bind(userId).first() as any\n\n if (!invitedUser) {\n return c.json({ error: 'User not found or invitation not valid' }, 404)\n }\n\n // Generate new invitation token\n const newInvitationToken = crypto.randomUUID()\n\n // Update invitation token and date\n const updateStmt = db.prepare(`\n UPDATE users SET \n invitation_token = ?, \n invited_at = ?, \n updated_at = ?\n WHERE id = ?\n `)\n\n await updateStmt.bind(\n newInvitationToken,\n Date.now(),\n Date.now(),\n userId\n ).run()\n\n // Log the activity\n await logActivity(\n db, user!.userId, 'user!.invitation_resent', 'users', userId,\n { email: invitedUser.email },\n c.req.header('x-forwarded-for') || c.req.header('cf-connecting-ip'),\n c.req.header('user-agent')\n )\n\n // Generate new invitation link\n const invitationLink = `${c.req.header('origin') || 'http://localhost:8787'}/auth/accept-invitation?token=${newInvitationToken}`\n\n return c.json({\n success: true,\n message: 'Invitation resent successfully',\n invitation_link: invitationLink\n })\n\n } catch (error) {\n console.error('Resend invitation error:', error)\n return c.json({ error: 'Failed to resend invitation' }, 500)\n }\n})\n\n/**\n * DELETE /admin/cancel-invitation/:id - Cancel invitation\n */\nuserRoutes.delete('/cancel-invitation/:id', async (c) => {\n const db = c.env.DB\n const user = c.get('user')\n const userId = c.req.param('id')\n\n try {\n // Check if user exists and is invited but not active\n const userStmt = db.prepare(`\n SELECT id, email FROM users \n WHERE id = ? AND is_active = 0 AND invitation_token IS NOT NULL\n `)\n const invitedUser = await userStmt.bind(userId).first() as any\n\n if (!invitedUser) {\n return c.json({ error: 'User not found or invitation not valid' }, 404)\n }\n\n // Delete the user record (since they haven't activated yet)\n const deleteStmt = db.prepare(`DELETE FROM users WHERE id = ?`)\n await deleteStmt.bind(userId).run()\n\n // Log the activity\n await logActivity(\n db, user!.userId, 'user!.invitation_cancelled', 'users', userId,\n { email: invitedUser.email },\n c.req.header('x-forwarded-for') || c.req.header('cf-connecting-ip'),\n c.req.header('user-agent')\n )\n\n return c.json({\n success: true,\n message: 'Invitation cancelled successfully'\n })\n\n } catch (error) {\n console.error('Cancel invitation error:', error)\n return c.json({ error: 'Failed to cancel invitation' }, 500)\n }\n})\n\n/**\n * GET /admin/activity-logs - View activity logs\n */\nuserRoutes.get('/activity-logs', async (c) => {\n const db = c.env.DB\n const user = c.get('user')\n\n try {\n // Get pagination and filter parameters\n const page = parseInt(c.req.query('page') || '1')\n const limit = parseInt(c.req.query('limit') || '50')\n const offset = (page - 1) * limit\n\n const filters = {\n action: c.req.query('action') || '',\n resource_type: c.req.query('resource_type') || '',\n date_from: c.req.query('date_from') || '',\n date_to: c.req.query('date_to') || '',\n user_id: c.req.query('user_id') || ''\n }\n\n // Build where clause\n let whereConditions: string[] = []\n let params: any[] = []\n\n if (filters.action) {\n whereConditions.push('al.action = ?')\n params.push(filters.action)\n }\n\n if (filters.resource_type) {\n whereConditions.push('al.resource_type = ?')\n params.push(filters.resource_type)\n }\n\n if (filters.user_id) {\n whereConditions.push('al.user_id = ?')\n params.push(filters.user_id)\n }\n\n if (filters.date_from) {\n const fromTimestamp = new Date(filters.date_from).getTime()\n whereConditions.push('al.created_at >= ?')\n params.push(fromTimestamp)\n }\n\n if (filters.date_to) {\n const toTimestamp = new Date(filters.date_to + ' 23:59:59').getTime()\n whereConditions.push('al.created_at <= ?')\n params.push(toTimestamp)\n }\n\n const whereClause = whereConditions.length > 0 ? `WHERE ${whereConditions.join(' AND ')}` : ''\n\n // Get activity logs with user information\n const logsStmt = db.prepare(`\n SELECT \n al.id, al.user_id, al.action, al.resource_type, al.resource_id,\n al.details, al.ip_address, al.user_agent, al.created_at,\n u.email as user_email,\n COALESCE(u.first_name || ' ' || u.last_name, u.username, u.email) as user_name\n FROM activity_logs al\n LEFT JOIN users u ON al.user_id = u.id\n ${whereClause}\n ORDER BY al.created_at DESC\n LIMIT ? OFFSET ?\n `)\n\n const { results: logs } = await logsStmt.bind(...params, limit, offset).all()\n\n // Get total count for pagination\n const countStmt = db.prepare(`\n SELECT COUNT(*) as total \n FROM activity_logs al\n LEFT JOIN users u ON al.user_id = u.id\n ${whereClause}\n `)\n const countResult = await countStmt.bind(...params).first() as any\n const totalLogs = countResult?.total || 0\n\n // Parse details JSON for each log\n const formattedLogs: ActivityLog[] = (logs || []).map((log: any) => ({\n ...log,\n details: log.details ? JSON.parse(log.details) : null\n }))\n\n // Log the activity\n await logActivity(\n db, user!.userId, 'activity.logs_viewed', undefined, undefined,\n { filters, page, limit },\n c.req.header('x-forwarded-for') || c.req.header('cf-connecting-ip'),\n c.req.header('user-agent')\n )\n\n const pageData: ActivityLogsPageData = {\n logs: formattedLogs,\n pagination: {\n page,\n limit,\n total: totalLogs,\n pages: Math.ceil(totalLogs / limit)\n },\n filters,\n user: {\n name: user!.email.split('@')[0] || user!.email, // Use email username as fallback\n email: user!.email,\n role: user!.role\n }\n }\n\n return c.html(renderActivityLogsPage(pageData))\n\n } catch (error) {\n console.error('Activity logs error:', error)\n \n const pageData: ActivityLogsPageData = {\n logs: [],\n pagination: { page: 1, limit: 50, total: 0, pages: 0 },\n filters: {},\n user: {\n name: user!.email,\n email: user!.email,\n role: user!.role\n }\n }\n\n return c.html(renderActivityLogsPage(pageData))\n }\n})\n\n/**\n * GET /admin/activity-logs/export - Export activity logs to CSV\n */\nuserRoutes.get('/activity-logs/export', async (c) => {\n const db = c.env.DB\n const user = c.get('user')\n\n try {\n // Get filter parameters (same as list view)\n const filters = {\n action: c.req.query('action') || '',\n resource_type: c.req.query('resource_type') || '',\n date_from: c.req.query('date_from') || '',\n date_to: c.req.query('date_to') || '',\n user_id: c.req.query('user_id') || ''\n }\n\n // Build where clause\n let whereConditions: string[] = []\n let params: any[] = []\n\n if (filters.action) {\n whereConditions.push('al.action = ?')\n params.push(filters.action)\n }\n\n if (filters.resource_type) {\n whereConditions.push('al.resource_type = ?')\n params.push(filters.resource_type)\n }\n\n if (filters.user_id) {\n whereConditions.push('al.user_id = ?')\n params.push(filters.user_id)\n }\n\n if (filters.date_from) {\n const fromTimestamp = new Date(filters.date_from).getTime()\n whereConditions.push('al.created_at >= ?')\n params.push(fromTimestamp)\n }\n\n if (filters.date_to) {\n const toTimestamp = new Date(filters.date_to + ' 23:59:59').getTime()\n whereConditions.push('al.created_at <= ?')\n params.push(toTimestamp)\n }\n\n const whereClause = whereConditions.length > 0 ? `WHERE ${whereConditions.join(' AND ')}` : ''\n\n // Get all matching activity logs (limit to 10,000 for performance)\n const logsStmt = db.prepare(`\n SELECT \n al.id, al.user_id, al.action, al.resource_type, al.resource_id,\n al.details, al.ip_address, al.user_agent, al.created_at,\n u.email as user_email,\n COALESCE(u.first_name || ' ' || u.last_name, u.username, u.email) as user_name\n FROM activity_logs al\n LEFT JOIN users u ON al.user_id = u.id\n ${whereClause}\n ORDER BY al.created_at DESC\n LIMIT 10000\n `)\n\n const { results: logs } = await logsStmt.bind(...params).all()\n\n // Generate CSV content\n const csvHeaders = ['Timestamp', 'User', 'Email', 'Action', 'Resource Type', 'Resource ID', 'IP Address', 'Details']\n const csvRows = [csvHeaders.join(',')]\n\n for (const log of (logs || [])) {\n const row = [\n `\"${new Date((log as any).created_at).toISOString()}\"`,\n `\"${(log as any).user_name || 'Unknown'}\"`,\n `\"${(log as any).user_email || 'N/A'}\"`,\n `\"${(log as any).action}\"`,\n `\"${(log as any).resource_type || 'N/A'}\"`,\n `\"${(log as any).resource_id || 'N/A'}\"`,\n `\"${(log as any).ip_address || 'N/A'}\"`,\n `\"${(log as any).details ? JSON.stringify(JSON.parse((log as any).details)) : 'N/A'}\"`\n ]\n csvRows.push(row.join(','))\n }\n\n const csvContent = csvRows.join('\\n')\n\n // Log the export activity\n await logActivity(\n db, user!.userId, 'activity.logs_exported', undefined, undefined,\n { filters, count: logs?.length || 0 },\n c.req.header('x-forwarded-for') || c.req.header('cf-connecting-ip'),\n c.req.header('user-agent')\n )\n\n // Return CSV file\n const filename = `activity-logs-${new Date().toISOString().split('T')[0]}.csv`\n \n return new Response(csvContent, {\n headers: {\n 'Content-Type': 'text/csv',\n 'Content-Disposition': `attachment; filename=\"${filename}\"`\n }\n })\n\n } catch (error) {\n console.error('Activity logs export error:', error)\n return c.json({ error: 'Failed to export activity logs' }, 500)\n }\n})\n\nexport { userRoutes }","export interface MediaFile {\n id: string;\n filename: string;\n original_name: string;\n mime_type: string;\n size: number;\n public_url: string;\n thumbnail_url?: string;\n alt?: string;\n caption?: string;\n tags: string[];\n uploaded_at: string;\n fileSize: string;\n uploadedAt: string;\n isImage: boolean;\n isVideo: boolean;\n isDocument: boolean;\n}\n\nexport interface MediaGridData {\n files: MediaFile[];\n viewMode?: \"grid\" | \"list\";\n selectable?: boolean;\n emptyMessage?: string;\n className?: string;\n}\n\nexport function renderMediaGrid(data: MediaGridData): string {\n if (data.files.length === 0) {\n return `\n <div class=\"text-center py-12\">\n <svg class=\"mx-auto h-12 w-12 text-zinc-400\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z\" />\n </svg>\n <h3 class=\"mt-2 text-sm font-medium text-zinc-950 dark:text-white\">No media files</h3>\n <p class=\"mt-1 text-sm text-zinc-500 dark:text-zinc-400\">${\n data.emptyMessage || \"Get started by uploading your first file.\"\n }</p>\n </div>\n `;\n }\n\n const gridClass = data.viewMode === \"list\" ? \"space-y-4\" : \"media-grid\";\n\n return `\n <div class=\"${gridClass} ${data.className || \"\"}\">\n ${data.files\n .map((file) =>\n renderMediaFileCard(file, data.viewMode, data.selectable)\n )\n .join(\"\")}\n </div>\n `;\n}\n\nexport function renderMediaFileCard(\n file: MediaFile,\n viewMode: \"grid\" | \"list\" = \"grid\",\n selectable: boolean = false\n): string {\n if (viewMode === \"list\") {\n return `\n <div class=\"media-item rounded-xl bg-white dark:bg-zinc-900 shadow-sm ring-1 ring-zinc-950/5 dark:ring-white/10 hover:shadow-md transition-all\" data-file-id=\"${\n file.id\n }\">\n <div class=\"flex items-center p-4\">\n ${\n selectable\n ? `\n <div class=\"flex h-6 shrink-0 items-center mr-4\">\n <div class=\"group grid size-4 grid-cols-1\">\n <input type=\"checkbox\" value=\"${file.id}\" onchange=\"toggleFileSelection('${file.id}')\" class=\"col-start-1 row-start-1 appearance-none rounded border border-zinc-950/10 dark:border-white/10 bg-white dark:bg-white/5 checked:border-indigo-500 checked:bg-indigo-500 indeterminate:border-indigo-500 indeterminate:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-500 disabled:border-zinc-950/5 dark:disabled:border-white/5 disabled:bg-zinc-950/10 dark:disabled:bg-white/10 disabled:checked:bg-zinc-950/10 dark:disabled:checked:bg-white/10 forced-colors:appearance-auto media-checkbox\" />\n <svg viewBox=\"0 0 14 14\" fill=\"none\" class=\"pointer-events-none col-start-1 row-start-1 size-3.5 self-center justify-self-center stroke-white group-has-[:disabled]:stroke-zinc-950/25 dark:group-has-[:disabled]:stroke-white/25\">\n <path d=\"M3 8L6 11L11 3.5\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"opacity-0 group-has-[:checked]:opacity-100\" />\n <path d=\"M3 7H11\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"opacity-0 group-has-[:indeterminate]:opacity-100\" />\n </svg>\n </div>\n </div>\n `\n : \"\"\n }\n\n <div class=\"flex-shrink-0 mr-4\">\n ${\n file.isImage\n ? `\n <img src=\"${file.thumbnail_url || file.public_url}\" alt=\"${\n file.alt || file.original_name\n }\"\n class=\"w-16 h-16 object-cover rounded-lg ring-1 ring-zinc-950/10 dark:ring-white/10\">\n `\n : `\n <div class=\"w-16 h-16 bg-zinc-100 dark:bg-zinc-800 rounded-lg flex items-center justify-center\">\n ${getFileIcon(file.mime_type)}\n </div>\n `\n }\n </div>\n\n <div class=\"flex-1 min-w-0\">\n <div class=\"flex items-center justify-between\">\n <h4 class=\"text-sm font-medium text-zinc-950 dark:text-white truncate\" title=\"${\n file.original_name\n }\">\n ${file.original_name}\n </h4>\n <div class=\"flex items-center space-x-2\">\n <span class=\"text-sm text-zinc-500 dark:text-zinc-400\">${\n file.fileSize\n }</span>\n <button\n class=\"text-zinc-500 dark:text-zinc-400 hover:text-zinc-950 dark:hover:text-white transition-colors\"\n hx-get=\"/admin/media/${file.id}/details\"\n hx-target=\"#file-modal-content\"\n onclick=\"document.getElementById('file-modal').classList.remove('hidden')\"\n >\n <svg class=\"w-5 h-5\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z\"></path>\n </svg>\n </button>\n </div>\n </div>\n <div class=\"mt-1 flex items-center text-sm text-zinc-500 dark:text-zinc-400\">\n <span>${file.uploadedAt}</span>\n ${\n file.tags.length > 0\n ? `\n <span class=\"mx-2\">•</span>\n <div class=\"flex items-center space-x-1\">\n ${file.tags\n .slice(0, 2)\n .map(\n (tag) => `\n <span class=\"inline-block px-2 py-1 text-xs rounded-lg bg-zinc-100 dark:bg-zinc-800 text-zinc-950 dark:text-white\">\n ${tag}\n </span>\n `\n )\n .join(\"\")}\n ${\n file.tags.length > 2\n ? `<span class=\"text-xs text-zinc-500 dark:text-zinc-400\">+${\n file.tags.length - 2\n }</span>`\n : \"\"\n }\n </div>\n `\n : \"\"\n }\n </div>\n </div>\n </div>\n </div>\n `;\n }\n\n // Grid view\n return `\n <div class=\"media-item relative rounded-xl bg-white dark:bg-zinc-900 shadow-sm ring-1 ring-zinc-950/5 dark:ring-white/10 hover:shadow-md transition-all duration-200 overflow-hidden group\" data-file-id=\"${\n file.id\n }\">\n ${\n selectable\n ? `\n <div class=\"absolute top-2 left-2 z-10\">\n <div class=\"flex h-6 shrink-0 items-center\">\n <div class=\"group grid size-4 grid-cols-1\">\n <input type=\"checkbox\" value=\"${file.id}\" onchange=\"toggleFileSelection('${file.id}')\" class=\"col-start-1 row-start-1 appearance-none rounded border border-zinc-950/10 dark:border-white/10 bg-white dark:bg-white/5 checked:border-indigo-500 checked:bg-indigo-500 indeterminate:border-indigo-500 indeterminate:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-500 disabled:border-zinc-950/5 dark:disabled:border-white/5 disabled:bg-zinc-950/10 dark:disabled:bg-white/10 disabled:checked:bg-zinc-950/10 dark:disabled:checked:bg-white/10 forced-colors:appearance-auto media-checkbox\" />\n <svg viewBox=\"0 0 14 14\" fill=\"none\" class=\"pointer-events-none col-start-1 row-start-1 size-3.5 self-center justify-self-center stroke-white group-has-[:disabled]:stroke-zinc-950/25 dark:group-has-[:disabled]:stroke-white/25\">\n <path d=\"M3 8L6 11L11 3.5\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"opacity-0 group-has-[:checked]:opacity-100\" />\n <path d=\"M3 7H11\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"opacity-0 group-has-[:indeterminate]:opacity-100\" />\n </svg>\n </div>\n </div>\n </div>\n `\n : \"\"\n }\n\n <div class=\"aspect-square relative\">\n ${\n file.isImage\n ? `\n <img src=\"${file.thumbnail_url || file.public_url}\" alt=\"${\n file.alt || file.original_name\n }\"\n class=\"w-full h-full object-cover\">\n `\n : `\n <div class=\"w-full h-full bg-zinc-100 dark:bg-zinc-800 flex items-center justify-center\">\n ${getFileIcon(file.mime_type)}\n </div>\n `\n }\n\n <!-- Overlay actions -->\n <div class=\"absolute inset-0 bg-black bg-opacity-0 group-hover:bg-opacity-40 transition-all duration-200 flex items-center justify-center opacity-0 group-hover:opacity-100\">\n <div class=\"flex space-x-2\">\n <button\n hx-get=\"/admin/media/${file.id}/details\"\n hx-target=\"#file-modal-content\"\n onclick=\"document.getElementById('file-modal').classList.remove('hidden')\"\n class=\"p-2 bg-white/20 rounded-full hover:bg-white/30 transition-colors\"\n >\n <svg class=\"w-5 h-5 text-white\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M15 12a3 3 0 11-6 0 3 3 0 016 0z\"></path>\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z\"></path>\n </svg>\n </button>\n <button\n onclick=\"event.stopPropagation(); copyToClipboard('${\n file.public_url\n }')\"\n class=\"p-2 bg-white/20 rounded-full hover:bg-white/30 transition-colors\"\n >\n <svg class=\"w-5 h-5 text-white\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z\"></path>\n </svg>\n </button>\n </div>\n </div>\n </div>\n\n <div class=\"p-3\">\n <h4 class=\"text-sm font-medium text-zinc-950 dark:text-white truncate\" title=\"${\n file.original_name\n }\">\n ${file.original_name}\n </h4>\n <div class=\"flex justify-between items-center mt-1\">\n <span class=\"text-xs text-zinc-500 dark:text-zinc-400\">${\n file.fileSize\n }</span>\n <span class=\"text-xs text-zinc-500 dark:text-zinc-400\">${\n file.uploadedAt\n }</span>\n </div>\n ${\n file.tags.length > 0\n ? `\n <div class=\"flex flex-wrap gap-1 mt-2\">\n ${file.tags\n .slice(0, 2)\n .map(\n (tag) => `\n <span class=\"inline-block px-2 py-1 text-xs rounded-lg bg-zinc-100 dark:bg-zinc-800 text-zinc-950 dark:text-white\">\n ${tag}\n </span>\n `\n )\n .join(\"\")}\n ${\n file.tags.length > 2\n ? `<span class=\"text-xs text-zinc-500 dark:text-zinc-400\">+${\n file.tags.length - 2\n }</span>`\n : \"\"\n }\n </div>\n `\n : \"\"\n }\n </div>\n </div>\n `;\n}\n\nfunction getFileIcon(mimeType: string): string {\n if (mimeType.startsWith(\"image/\")) {\n return `\n <svg class=\"w-8 h-8 text-gray-400\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z\" />\n </svg>\n `;\n } else if (mimeType.startsWith(\"video/\")) {\n return `\n <svg class=\"w-8 h-8 text-gray-400\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M15 10l4.553-2.276A1 1 0 0121 8.618v6.764a1 1 0 01-1.447.894L15 14M5 18h8a2 2 0 002-2V8a2 2 0 00-2-2H5a2 2 0 00-2 2v8a2 2 0 002 2z\" />\n </svg>\n `;\n } else if (mimeType === \"application/pdf\") {\n return `\n <svg class=\"w-8 h-8 text-red-400\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M7 21h10a2 2 0 002-2V9.414a1 1 0 00-.293-.707l-5.414-5.414A1 1 0 0012.586 3H7a2 2 0 00-2 2v14a2 2 0 002 2z\" />\n </svg>\n `;\n } else {\n return `\n <svg class=\"w-8 h-8 text-gray-400\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z\" />\n </svg>\n `;\n }\n}\n","import {\n getConfirmationDialogScript,\n renderConfirmationDialog,\n} from \"../components/confirmation-dialog.template\";\nimport { MediaFile, renderMediaGrid } from \"../components/media-grid.template\";\nimport {\n AdminLayoutCatalystData,\n renderAdminLayoutCatalyst,\n} from \"../layouts/admin-layout-catalyst.template\";\n\nexport interface FolderStats {\n folder: string;\n count: number;\n totalSize: number;\n}\n\nexport interface TypeStats {\n type: string;\n count: number;\n}\n\nexport interface MediaLibraryPageData {\n files: MediaFile[];\n folders: FolderStats[];\n types: TypeStats[];\n currentFolder: string;\n currentType: string;\n currentView: \"grid\" | \"list\";\n currentPage: number;\n totalFiles: number;\n hasNextPage: boolean;\n user?: {\n name: string;\n email: string;\n role: string;\n };\n version?: string;\n}\n\nexport function renderMediaLibraryPage(data: MediaLibraryPageData): string {\n const pageContent = `\n <div>\n <!-- Header -->\n <div class=\"sm:flex sm:items-center sm:justify-between mb-6\">\n <div class=\"sm:flex-auto\">\n <h1 class=\"text-2xl/8 font-semibold text-zinc-950 dark:text-white sm:text-xl/8\">Media Library</h1>\n <p class=\"mt-2 text-sm/6 text-zinc-500 dark:text-zinc-400\">Manage your media files and assets</p>\n </div>\n <div class=\"mt-4 sm:mt-0 sm:ml-16 flex gap-x-2\">\n <button\n class=\"inline-flex items-center justify-center rounded-lg bg-zinc-950 dark:bg-white px-3.5 py-2.5 text-sm font-semibold text-white dark:text-zinc-950 hover:bg-zinc-800 dark:hover:bg-zinc-100 transition-colors shadow-sm\"\n onclick=\"document.getElementById('upload-modal').classList.remove('hidden')\"\n >\n <svg class=\"-ml-0.5 mr-1.5 h-5 w-5\" viewBox=\"0 0 20 20\" fill=\"currentColor\">\n <path d=\"M10.75 4.75a.75.75 0 00-1.5 0v4.5h-4.5a.75.75 0 000 1.5h4.5v4.5a.75.75 0 001.5 0v-4.5h4.5a.75.75 0 000-1.5h-4.5v-4.5z\" />\n </svg>\n Upload Media\n </button>\n </div>\n </div>\n \n <div class=\"flex gap-6\">\n <!-- Sidebar -->\n <div class=\"w-64 rounded-xl bg-white dark:bg-zinc-900 shadow-sm ring-1 ring-zinc-950/5 dark:ring-white/10 p-6\">\n <div class=\"space-y-6\">\n <!-- Upload Button -->\n <div>\n <button\n class=\"w-full rounded-lg bg-zinc-950 dark:bg-white px-4 py-2.5 text-sm font-semibold text-white dark:text-zinc-950 hover:bg-zinc-800 dark:hover:bg-zinc-100 transition-colors shadow-sm\"\n onclick=\"document.getElementById('upload-modal').classList.remove('hidden')\"\n >\n Upload Files\n </button>\n </div>\n\n <!-- Folders -->\n <div>\n <h3 class=\"text-sm font-medium text-zinc-950 dark:text-white mb-3\">Folders</h3>\n <ul class=\"space-y-1\">\n <li>\n <a href=\"/admin/media?folder=all\"\n class=\"block px-3 py-2 text-sm rounded-lg transition-colors ${\n data.currentFolder === \"all\"\n ? \"bg-zinc-950 dark:bg-white text-white dark:text-zinc-950 font-medium\"\n : \"text-zinc-700 dark:text-zinc-300 hover:text-zinc-950 dark:hover:text-white hover:bg-zinc-50 dark:hover:bg-zinc-800/50\"\n }\">\n All Files (${data.totalFiles})\n </a>\n </li>\n ${data.folders\n .map(\n (folder) => `\n <li>\n <a href=\"/admin/media?folder=${folder.folder}\"\n class=\"block px-3 py-2 text-sm rounded-lg transition-colors ${\n data.currentFolder === folder.folder\n ? \"bg-zinc-950 dark:bg-white text-white dark:text-zinc-950 font-medium\"\n : \"text-zinc-700 dark:text-zinc-300 hover:text-zinc-950 dark:hover:text-white hover:bg-zinc-50 dark:hover:bg-zinc-800/50\"\n }\">\n ${folder.folder} (${folder.count})\n </a>\n </li>\n `\n )\n .join(\"\")}\n </ul>\n </div>\n\n <!-- File Types -->\n <div>\n <h3 class=\"text-sm font-medium text-zinc-950 dark:text-white mb-3\">File Types</h3>\n <ul class=\"space-y-1\">\n <li>\n <a href=\"/admin/media?type=all\"\n class=\"block px-3 py-2 text-sm rounded-lg transition-colors ${\n data.currentType === \"all\"\n ? \"bg-zinc-950 dark:bg-white text-white dark:text-zinc-950 font-medium\"\n : \"text-zinc-700 dark:text-zinc-300 hover:text-zinc-950 dark:hover:text-white hover:bg-zinc-50 dark:hover:bg-zinc-800/50\"\n }\">\n All Types\n </a>\n </li>\n ${data.types\n .map(\n (type) => `\n <li>\n <a href=\"/admin/media?type=${type.type}\"\n class=\"block px-3 py-2 text-sm rounded-lg transition-colors ${\n data.currentType === type.type\n ? \"bg-zinc-950 dark:bg-white text-white dark:text-zinc-950 font-medium\"\n : \"text-zinc-700 dark:text-zinc-300 hover:text-zinc-950 dark:hover:text-white hover:bg-zinc-50 dark:hover:bg-zinc-800/50\"\n }\">\n ${\n type.type.charAt(0).toUpperCase() + type.type.slice(1)\n } (${type.count})\n </a>\n </li>\n `\n )\n .join(\"\")}\n </ul>\n </div>\n\n <!-- Quick Actions -->\n <div>\n <h3 class=\"text-sm font-medium text-zinc-950 dark:text-white mb-3\">Quick Actions</h3>\n <div class=\"space-y-2\">\n <button\n onclick=\"openCreateFolderModal()\"\n class=\"w-full text-left px-3 py-2 text-sm text-zinc-700 dark:text-zinc-300 hover:text-zinc-950 dark:hover:text-white hover:bg-zinc-50 dark:hover:bg-zinc-800/50 rounded-lg transition-colors\">\n Create Folder\n </button>\n <button\n class=\"w-full text-left px-3 py-2 text-sm text-zinc-700 dark:text-zinc-300 hover:text-zinc-950 dark:hover:text-white hover:bg-zinc-50 dark:hover:bg-zinc-800/50 rounded-lg transition-colors\"\n hx-delete=\"/admin/media/cleanup\"\n hx-confirm=\"Delete unused files?\"\n hx-target=\"body\"\n hx-swap=\"beforeend\"\n >\n Cleanup Unused\n </button>\n </div>\n </div>\n </div>\n </div>\n \n <!-- Main Content -->\n <div class=\"flex-1\">\n <!-- Toolbar -->\n <div class=\"relative rounded-xl mb-6 z-10\">\n <!-- Gradient Background -->\n <div class=\"absolute inset-0 bg-gradient-to-r from-cyan-500/10 via-pink-500/10 to-purple-500/10 dark:from-cyan-400/20 dark:via-pink-400/20 dark:to-purple-400/20\"></div>\n\n <div class=\"relative bg-white dark:bg-zinc-900 shadow-sm ring-1 ring-zinc-950/5 dark:ring-white/10\">\n <div class=\"px-6 py-5\">\n <div class=\"flex items-center justify-between\">\n <div class=\"flex items-center space-x-4\">\n <div class=\"flex items-center space-x-2\">\n <label class=\"text-sm/6 font-medium text-zinc-950 dark:text-white\">View:</label>\n <div class=\"grid grid-cols-1\">\n <select\n class=\"col-start-1 row-start-1 w-full appearance-none rounded-md bg-white/5 dark:bg-white/5 py-1.5 pl-3 pr-8 text-base text-zinc-950 dark:text-white outline outline-1 -outline-offset-1 outline-cyan-500/30 dark:outline-cyan-400/30 *:bg-white dark:*:bg-zinc-800 focus-visible:outline focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-cyan-500 dark:focus-visible:outline-cyan-400 sm:text-sm/6 min-w-32\"\n onchange=\"window.location.href = updateUrlParam('view', this.value)\"\n >\n <option value=\"grid\" ${\n data.currentView === \"grid\" ? \"selected\" : \"\"\n }>Grid</option>\n <option value=\"list\" ${\n data.currentView === \"list\" ? \"selected\" : \"\"\n }>List</option>\n </select>\n <svg class=\"pointer-events-none col-start-1 row-start-1 mr-2 size-5 self-center justify-self-end text-zinc-500 dark:text-zinc-400 sm:size-4\" viewBox=\"0 0 16 16\" fill=\"currentColor\" aria-hidden=\"true\">\n <path fill-rule=\"evenodd\" d=\"M4.22 6.22a.75.75 0 0 1 1.06 0L8 8.94l2.72-2.72a.75.75 0 1 1 1.06 1.06l-3.25 3.25a.75.75 0 0 1-1.06 0L4.22 7.28a.75.75 0 0 1 0-1.06Z\" clip-rule=\"evenodd\" />\n </svg>\n </div>\n </div>\n\n <div class=\"relative group\">\n <input\n type=\"text\"\n id=\"media-search-input\"\n name=\"search\"\n placeholder=\"Search files...\"\n oninput=\"toggleMediaClearButton()\"\n class=\"rounded-full bg-white/90 dark:bg-zinc-800/90 backdrop-blur-sm px-4 py-2.5 pl-11 pr-10 text-sm w-72 text-zinc-950 dark:text-white border-2 border-cyan-200/50 dark:border-cyan-700/50 placeholder:text-zinc-400 dark:placeholder:text-zinc-500 focus:outline-none focus:border-cyan-500 dark:focus:border-cyan-400 focus:bg-white dark:focus:bg-zinc-800 focus:shadow-lg focus:shadow-cyan-500/20 dark:focus:shadow-cyan-400/20 transition-all duration-300\"\n hx-get=\"/admin/media/search\"\n hx-trigger=\"keyup changed delay:300ms\"\n hx-target=\"#media-grid\"\n hx-include=\"[name='folder'], [name='type']\"\n >\n <div class=\"absolute left-3.5 top-2.5 flex items-center justify-center w-5 h-5 rounded-full bg-gradient-to-br from-cyan-400 to-blue-500 dark:from-cyan-300 dark:to-blue-400 opacity-90 group-focus-within:opacity-100 transition-opacity\">\n <svg class=\"h-3 w-3 text-white\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\" stroke-width=\"2.5\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z\"/>\n </svg>\n </div>\n <button\n type=\"button\"\n id=\"clear-media-search\"\n class=\"hidden absolute right-3 top-2.5 p-0.5 rounded-full bg-zinc-200/80 dark:bg-zinc-700/80 hover:bg-zinc-300 dark:hover:bg-zinc-600 transition-colors\"\n onclick=\"clearMediaSearch()\"\n title=\"Clear search\"\n >\n <svg class=\"h-3.5 w-3.5 text-zinc-600 dark:text-zinc-300\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\" stroke-width=\"2.5\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M6 18L18 6M6 6l12 12\"/>\n </svg>\n </button>\n <input type=\"hidden\" name=\"folder\" value=\"${\n data.currentFolder\n }\">\n <input type=\"hidden\" name=\"type\" value=\"${\n data.currentType\n }\">\n </div>\n </div>\n\n <div class=\"flex items-center gap-x-3\">\n <span class=\"text-sm/6 font-medium text-zinc-700 dark:text-zinc-300 px-3 py-1.5 rounded-full bg-white/60 dark:bg-zinc-800/60 backdrop-blur-sm\">${\n data.files.length\n } files</span>\n <button\n id=\"select-all-btn\"\n class=\"inline-flex items-center gap-x-1.5 px-3 py-1.5 bg-white/90 dark:bg-zinc-800/90 backdrop-blur-sm text-zinc-950 dark:text-white text-sm font-medium rounded-full ring-1 ring-inset ring-cyan-200/50 dark:ring-cyan-700/50 hover:bg-gradient-to-r hover:from-cyan-50 hover:to-pink-50 dark:hover:from-cyan-900/30 dark:hover:to-pink-900/30 hover:ring-cyan-300 dark:hover:ring-cyan-600 transition-all duration-200\"\n onclick=\"toggleSelectAll()\"\n >\n Select All\n </button>\n <div class=\"relative inline-block z-50\" id=\"bulk-actions-dropdown\">\n <button\n id=\"bulk-actions-btn\"\n onclick=\"toggleBulkActionsDropdown()\"\n class=\"inline-flex items-center gap-x-1.5 px-3 py-1.5 bg-zinc-100/60 dark:bg-zinc-800/60 backdrop-blur-sm text-zinc-400 dark:text-zinc-600 text-sm font-medium rounded-full ring-1 ring-inset ring-zinc-200/50 dark:ring-zinc-700/50 cursor-not-allowed\"\n disabled\n >\n Bulk Actions\n <svg viewBox=\"0 0 20 20\" fill=\"currentColor\" class=\"size-4\">\n <path d=\"M5.22 8.22a.75.75 0 0 1 1.06 0L10 11.94l3.72-3.72a.75.75 0 1 1 1.06 1.06l-4.25 4.25a.75.75 0 0 1-1.06 0L5.22 9.28a.75.75 0 0 1 0-1.06Z\" clip-rule=\"evenodd\" fill-rule=\"evenodd\" />\n </svg>\n </button>\n\n <div\n id=\"bulk-actions-menu\"\n class=\"hidden absolute right-0 mt-2 w-56 origin-top-right divide-y divide-zinc-200 dark:divide-white/10 rounded-lg bg-white dark:bg-zinc-900 shadow-xl ring-1 ring-zinc-950/5 dark:ring-white/10 transition-all duration-100 scale-95 opacity-0 z-50\"\n style=\"transition-behavior: allow-discrete;\"\n >\n <div class=\"py-1\">\n <button\n onclick=\"openMoveToFolderModal()\"\n class=\"group/item flex w-full items-center px-4 py-2 text-sm text-zinc-700 dark:text-zinc-300 hover:bg-zinc-50 dark:hover:bg-white/5 hover:text-zinc-950 dark:hover:text-white transition-colors\"\n >\n <svg viewBox=\"0 0 20 20\" fill=\"currentColor\" class=\"mr-3 size-5 text-zinc-400 dark:text-zinc-500 group-hover/item:text-zinc-950 dark:group-hover/item:text-white\">\n <path d=\"M2 6a2 2 0 0 1 2-2h5.532a2 2 0 0 1 1.536.72l1.9 2.28a1 1 0 0 0 .768.36H17a2 2 0 0 1 2 2v3a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V6Z\" />\n </svg>\n Move to Folder\n </button>\n </div>\n <div class=\"py-1\">\n <button\n onclick=\"confirmBulkDelete()\"\n class=\"group/item flex w-full items-center px-4 py-2 text-sm text-zinc-700 dark:text-zinc-300 hover:bg-red-50 dark:hover:bg-red-500/10 hover:text-red-600 dark:hover:text-red-400 transition-colors\"\n >\n <svg viewBox=\"0 0 20 20\" fill=\"currentColor\" class=\"mr-3 size-5 text-zinc-400 dark:text-zinc-500 group-hover/item:text-red-600 dark:group-hover/item:text-red-400\">\n <path fill-rule=\"evenodd\" d=\"M8.75 1A2.75 2.75 0 0 0 6 3.75v.443c-.795.077-1.584.176-2.365.298a.75.75 0 1 0 .23 1.482l.149-.022.841 10.518A2.75 2.75 0 0 0 7.596 19h4.807a2.75 2.75 0 0 0 2.742-2.53l.841-10.52.149.023a.75.75 0 0 0 .23-1.482A41.03 41.03 0 0 0 14 4.193V3.75A2.75 2.75 0 0 0 11.25 1h-2.5ZM10 4c.84 0 1.673.025 2.5.075V3.75c0-.69-.56-1.25-1.25-1.25h-2.5c-.69 0-1.25.56-1.25 1.25v.325C8.327 4.025 9.16 4 10 4ZM8.58 7.72a.75.75 0 0 0-1.5.06l.3 7.5a.75.75 0 1 0 1.5-.06l-.3-7.5Zm4.34.06a.75.75 0 1 0-1.5-.06l-.3 7.5a.75.75 0 1 0 1.5.06l.3-7.5Z\" clip-rule=\"evenodd\" fill-rule=\"evenodd\" />\n </svg>\n Delete Selected Files\n </button>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n \n <!-- Media Grid -->\n <div id=\"media-grid\">\n ${renderMediaGrid({\n files: data.files,\n viewMode: data.currentView,\n selectable: true,\n emptyMessage:\n \"No media files found. Upload your first file to get started.\",\n })}\n </div>\n \n <!-- Pagination -->\n ${\n data.hasNextPage\n ? `\n <div class=\"mt-6 flex justify-center\">\n <div class=\"flex space-x-2\">\n ${\n data.currentPage > 1\n ? `\n <a href=\"${buildPageUrl(\n data.currentPage - 1,\n data.currentFolder,\n data.currentType\n )}\"\n class=\"rounded-lg bg-white dark:bg-zinc-800 px-3 py-2 text-sm font-semibold text-zinc-950 dark:text-white ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 hover:bg-zinc-50 dark:hover:bg-zinc-700 transition-colors\">\n Previous\n </a>\n `\n : \"\"\n }\n <span class=\"px-3 py-2 text-sm text-zinc-500 dark:text-zinc-400\">Page ${\n data.currentPage\n }</span>\n <a href=\"${buildPageUrl(\n data.currentPage + 1,\n data.currentFolder,\n data.currentType\n )}\"\n class=\"rounded-lg bg-white dark:bg-zinc-800 px-3 py-2 text-sm font-semibold text-zinc-950 dark:text-white ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 hover:bg-zinc-50 dark:hover:bg-zinc-700 transition-colors\">\n Next\n </a>\n </div>\n </div>\n `\n : \"\"\n }\n </div>\n </div>\n </div>\n \n <!-- Upload Modal -->\n <div id=\"upload-modal\" class=\"hidden fixed inset-0 bg-black/50 backdrop-blur-sm flex items-center justify-center z-50\">\n <div class=\"rounded-xl bg-white dark:bg-zinc-900 shadow-xl ring-1 ring-zinc-950/5 dark:ring-white/10 p-6 w-full max-w-2xl\">\n <div class=\"flex justify-between items-center mb-4\">\n <h3 class=\"text-lg font-semibold text-zinc-950 dark:text-white\">Upload Files</h3>\n <button onclick=\"document.getElementById('upload-modal').classList.add('hidden')\" class=\"text-zinc-500 dark:text-zinc-400 hover:text-zinc-950 dark:hover:text-white transition-colors\">\n <svg class=\"w-6 h-6\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M6 18L18 6M6 6l12 12\"></path>\n </svg>\n </button>\n </div>\n \n <!-- Upload Form -->\n <form\n id=\"upload-form\"\n hx-post=\"/admin/media/upload\"\n hx-encoding=\"multipart/form-data\"\n hx-target=\"#upload-results\"\n hx-on::after-request=\"if(event.detail.successful) { setTimeout(() => { window.location.href = '/admin/media?t=' + Date.now(); }, 1500); }\"\n class=\"space-y-4\"\n >\n <!-- Drag and Drop Zone -->\n <div\n id=\"upload-zone\"\n class=\"upload-zone border-2 border-dashed border-zinc-950/10 dark:border-white/20 rounded-xl p-8 text-center cursor-pointer bg-zinc-50 dark:bg-zinc-800/50 hover:bg-zinc-100 dark:hover:bg-zinc-800 transition-colors\"\n onclick=\"document.getElementById('file-input').click()\"\n >\n <svg class=\"mx-auto h-12 w-12 text-zinc-400\" stroke=\"currentColor\" fill=\"none\" viewBox=\"0 0 48 48\">\n <path d=\"M28 8H12a4 4 0 00-4 4v20m32-12v8m0 0v8a4 4 0 01-4 4H12a4 4 0 01-4-4v-4m32-4l-3.172-3.172a4 4 0 00-5.656 0L28 28M8 32l9.172-9.172a4 4 0 015.656 0L28 28m0 0l4 4m4-24h8m-4-4v8m-12 4h.02\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n </svg>\n <div class=\"mt-4\">\n <p class=\"text-lg text-zinc-950 dark:text-white\">Drop files here or click to upload</p>\n <p class=\"text-sm text-zinc-500 dark:text-zinc-400\">PNG, JPG, GIF, PDF up to 10MB</p>\n </div>\n </div>\n \n <input \n type=\"file\" \n id=\"file-input\" \n name=\"files\" \n multiple \n accept=\"image/*,application/pdf,text/plain\"\n class=\"hidden\"\n onchange=\"handleFileSelect(this.files)\"\n >\n \n <!-- Folder Selection -->\n <div>\n <label class=\"block text-sm font-medium text-zinc-950 dark:text-white mb-2\">Upload to folder:</label>\n <select name=\"folder\" class=\"w-full rounded-lg bg-white dark:bg-zinc-800 px-3 py-2 text-sm text-zinc-950 dark:text-white shadow-sm ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 focus:outline-none focus:ring-2 focus:ring-zinc-950 dark:focus:ring-white transition-shadow\">\n <option value=\"uploads\">uploads</option>\n <option value=\"images\">images</option>\n <option value=\"documents\">documents</option>\n </select>\n </div>\n\n <!-- File List -->\n <div id=\"file-list\" class=\"hidden\">\n <h4 class=\"text-sm font-medium text-zinc-950 dark:text-white mb-2\">Selected Files:</h4>\n <div id=\"selected-files\" class=\"space-y-2 max-h-40 overflow-y-auto\"></div>\n </div>\n\n <!-- Upload Button -->\n <div class=\"flex justify-end space-x-2\">\n <button\n type=\"button\"\n onclick=\"document.getElementById('upload-modal').classList.add('hidden')\"\n class=\"rounded-lg bg-white dark:bg-zinc-800 px-4 py-2.5 text-sm font-semibold text-zinc-950 dark:text-white shadow-sm ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 hover:bg-zinc-50 dark:hover:bg-zinc-700 transition-colors\"\n >\n Cancel\n </button>\n <button\n type=\"submit\"\n id=\"upload-btn\"\n class=\"rounded-lg bg-zinc-950 dark:bg-white px-4 py-2.5 text-sm font-semibold text-white dark:text-zinc-950 hover:bg-zinc-800 dark:hover:bg-zinc-100 disabled:opacity-50 transition-colors shadow-sm\"\n disabled\n >\n Upload Files\n </button>\n </div>\n </form>\n \n <!-- Upload Results -->\n <div id=\"upload-results\" class=\"mt-4\"></div>\n </div>\n </div>\n \n <!-- File Details Modal -->\n <div id=\"file-modal\" class=\"hidden fixed inset-0 bg-black/50 backdrop-blur-sm flex items-center justify-center z-50\">\n <div id=\"file-modal-content\" class=\"rounded-xl bg-white dark:bg-zinc-900 shadow-xl ring-1 ring-zinc-950/5 dark:ring-white/10 p-6 w-full max-w-4xl max-h-screen overflow-y-auto\">\n <!-- Content loaded via HTMX -->\n </div>\n </div>\n\n <!-- Move to Folder Modal -->\n <div id=\"move-to-folder-modal\" class=\"hidden fixed inset-0 bg-black/50 backdrop-blur-sm flex items-center justify-center z-50\">\n <div class=\"rounded-xl bg-white dark:bg-zinc-900 shadow-xl ring-1 ring-zinc-950/5 dark:ring-white/10 p-6 w-full max-w-md\">\n <div class=\"flex justify-between items-center mb-4\">\n <h3 class=\"text-lg font-semibold text-zinc-950 dark:text-white\">Move to Folder</h3>\n <button onclick=\"closeMoveToFolderModal()\" class=\"text-zinc-500 dark:text-zinc-400 hover:text-zinc-950 dark:hover:text-white transition-colors\">\n <svg class=\"w-6 h-6\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M6 18L18 6M6 6l12 12\"></path>\n </svg>\n </button>\n </div>\n\n <p class=\"text-sm text-zinc-500 dark:text-zinc-400 mb-4\">\n Select a folder to move <span id=\"move-file-count\" class=\"font-medium text-zinc-950 dark:text-white\">0</span> selected file(s) to:\n </p>\n\n <div class=\"space-y-2 mb-6\">\n ${\n data.folders.length > 0\n ? data.folders\n .map(\n (folder) => `\n <button\n onclick=\"performBulkMove('${folder.folder}')\"\n class=\"w-full text-left px-4 py-3 rounded-lg bg-zinc-50 dark:bg-zinc-800/50 hover:bg-zinc-100 dark:hover:bg-zinc-800 text-zinc-950 dark:text-white transition-colors ring-1 ring-inset ring-zinc-200 dark:ring-zinc-700\"\n >\n <div class=\"flex items-center justify-between\">\n <span class=\"font-medium\">${folder.folder}</span>\n <span class=\"text-sm text-zinc-500 dark:text-zinc-400\">${folder.count} files</span>\n </div>\n </button>\n `\n )\n .join(\"\")\n : '<p class=\"text-sm text-zinc-500 dark:text-zinc-400 text-center py-4\">No folders available</p>'\n }\n </div>\n\n <div class=\"flex justify-end space-x-2\">\n <button\n onclick=\"closeMoveToFolderModal()\"\n class=\"rounded-lg bg-white dark:bg-zinc-800 px-4 py-2.5 text-sm font-semibold text-zinc-950 dark:text-white shadow-sm ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 hover:bg-zinc-50 dark:hover:bg-zinc-700 transition-colors\"\n >\n Cancel\n </button>\n </div>\n </div>\n </div>\n\n <!-- Create Folder Modal -->\n <div id=\"create-folder-modal\" class=\"hidden fixed inset-0 bg-black/50 backdrop-blur-sm flex items-center justify-center z-50\">\n <div class=\"rounded-xl bg-white dark:bg-zinc-900 shadow-xl ring-1 ring-zinc-950/5 dark:ring-white/10 p-6 w-full max-w-md\">\n <div class=\"flex justify-between items-center mb-4\">\n <h3 class=\"text-lg font-semibold text-zinc-950 dark:text-white\">Create New Folder</h3>\n <button onclick=\"closeCreateFolderModal()\" aria-label=\"Close\" class=\"text-zinc-500 dark:text-zinc-400 hover:text-zinc-950 dark:hover:text-white transition-colors\">\n <svg class=\"w-6 h-6\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M6 18L18 6M6 6l12 12\"></path>\n </svg>\n </button>\n </div>\n\n <form onsubmit=\"createNewFolder(event)\" class=\"space-y-4\">\n <div>\n <label for=\"folder-name\" class=\"block text-sm font-medium text-zinc-950 dark:text-white mb-2\">\n Folder Name\n </label>\n <input\n type=\"text\"\n id=\"folder-name\"\n name=\"folderName\"\n placeholder=\"e.g., images, documents\"\n required\n pattern=\"[a-z0-9-_]+\"\n title=\"Only lowercase letters, numbers, hyphens, and underscores allowed\"\n class=\"w-full rounded-lg bg-white dark:bg-zinc-800 px-3 py-2 text-sm text-zinc-950 dark:text-white shadow-sm ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 focus:outline-none focus:ring-2 focus:ring-cyan-500 dark:focus:ring-cyan-400 transition-shadow\"\n >\n <p class=\"mt-1 text-xs text-zinc-500 dark:text-zinc-400\">\n Use lowercase letters, numbers, hyphens, and underscores only\n </p>\n </div>\n\n <div class=\"flex justify-end space-x-2\">\n <button\n type=\"button\"\n onclick=\"closeCreateFolderModal()\"\n class=\"rounded-lg bg-white dark:bg-zinc-800 px-4 py-2.5 text-sm font-semibold text-zinc-950 dark:text-white shadow-sm ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 hover:bg-zinc-50 dark:hover:bg-zinc-700 transition-colors\"\n >\n Cancel\n </button>\n <button\n type=\"submit\"\n class=\"rounded-lg bg-zinc-950 dark:bg-white px-4 py-2.5 text-sm font-semibold text-white dark:text-zinc-950 hover:bg-zinc-800 dark:hover:bg-zinc-100 transition-colors shadow-sm\"\n >\n Create Folder\n </button>\n </div>\n </form>\n </div>\n </div>\n\n <style>\n .media-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 1rem; }\n .media-item { position: relative; border-radius: 8px; overflow: hidden; transition: transform 0.2s; }\n .media-item:hover { transform: scale(1.02); }\n .media-item.selected { ring: 2px solid rgba(255, 255, 255, 0.4); }\n .upload-zone { border: 2px dashed rgba(255, 255, 255, 0.2); background: rgba(255, 255, 255, 0.1); min-height: 200px; }\n .upload-zone.dragover { border-color: rgba(255, 255, 255, 0.4); background: rgba(255, 255, 255, 0.2); }\n .file-icon { width: 48px; height: 48px; }\n .preview-overlay { position: absolute; top: 0; left: 0; right: 0; bottom: 0; background: rgba(0,0,0,0.7); opacity: 0; transition: opacity 0.2s; }\n .media-item:hover .preview-overlay { opacity: 1; }\n </style>\n \n <script>\n let selectedFiles = new Set();\n let dragDropFiles = [];\n \n // File selection handling\n function toggleFileSelection(fileId) {\n if (selectedFiles.has(fileId)) {\n selectedFiles.delete(fileId);\n document.querySelector(\\`[data-file-id=\"\\${fileId}\"]\\`).classList.remove('selected');\n } else {\n selectedFiles.add(fileId);\n document.querySelector(\\`[data-file-id=\"\\${fileId}\"]\\`).classList.add('selected');\n }\n updateBulkActionsButton();\n }\n \n function toggleSelectAll() {\n const allItems = document.querySelectorAll('[data-file-id]');\n if (selectedFiles.size === allItems.length) {\n selectedFiles.clear();\n allItems.forEach(item => item.classList.remove('selected'));\n document.getElementById('select-all-btn').textContent = 'Select All';\n } else {\n allItems.forEach(item => {\n const fileId = item.dataset.fileId;\n selectedFiles.add(fileId);\n item.classList.add('selected');\n });\n document.getElementById('select-all-btn').textContent = 'Deselect All';\n }\n updateBulkActionsButton();\n }\n \n function updateBulkActionsButton() {\n const btn = document.getElementById('bulk-actions-btn');\n const chevronIcon = btn.querySelector('svg');\n\n if (selectedFiles.size > 0) {\n btn.disabled = false;\n btn.className = 'inline-flex items-center gap-x-1.5 px-3 py-1.5 bg-white/90 dark:bg-zinc-800/90 backdrop-blur-sm text-zinc-950 dark:text-white text-sm font-medium rounded-full ring-1 ring-inset ring-cyan-200/50 dark:ring-cyan-700/50 hover:bg-gradient-to-r hover:from-cyan-50 hover:to-blue-50 dark:hover:from-cyan-900/30 dark:hover:to-blue-900/30 hover:ring-cyan-300 dark:hover:ring-cyan-600 transition-all duration-200';\n btn.innerHTML = \\`Actions (\\${selectedFiles.size}) <svg viewBox=\"0 0 20 20\" fill=\"currentColor\" class=\"size-4\"><path d=\"M5.22 8.22a.75.75 0 0 1 1.06 0L10 11.94l3.72-3.72a.75.75 0 1 1 1.06 1.06l-4.25 4.25a.75.75 0 0 1-1.06 0L5.22 9.28a.75.75 0 0 1 0-1.06Z\" clip-rule=\"evenodd\" fill-rule=\"evenodd\" /></svg>\\`;\n // Re-attach onclick handler after innerHTML update\n btn.onclick = toggleBulkActionsDropdown;\n } else {\n btn.disabled = true;\n btn.className = 'inline-flex items-center gap-x-1.5 px-3 py-1.5 bg-zinc-100/60 dark:bg-zinc-800/60 backdrop-blur-sm text-zinc-400 dark:text-zinc-600 text-sm font-medium rounded-full ring-1 ring-inset ring-zinc-200/50 dark:ring-zinc-700/50 cursor-not-allowed';\n btn.innerHTML = \\`Bulk Actions <svg viewBox=\"0 0 20 20\" fill=\"currentColor\" class=\"size-4\"><path d=\"M5.22 8.22a.75.75 0 0 1 1.06 0L10 11.94l3.72-3.72a.75.75 0 1 1 1.06 1.06l-4.25 4.25a.75.75 0 0 1-1.06 0L5.22 9.28a.75.75 0 0 1 0-1.06Z\" clip-rule=\"evenodd\" fill-rule=\"evenodd\" /></svg>\\`;\n btn.onclick = null; // Remove handler when disabled\n // Hide menu when no files selected\n const menu = document.getElementById('bulk-actions-menu');\n menu.classList.remove('scale-100', 'opacity-100');\n menu.classList.add('scale-95', 'opacity-0', 'hidden');\n }\n }\n\n function toggleBulkActionsDropdown() {\n const menu = document.getElementById('bulk-actions-menu');\n const isHidden = menu.classList.contains('hidden');\n\n if (isHidden) {\n menu.classList.remove('hidden');\n setTimeout(() => {\n menu.classList.remove('scale-95', 'opacity-0');\n menu.classList.add('scale-100', 'opacity-100');\n }, 10);\n } else {\n menu.classList.remove('scale-100', 'opacity-100');\n menu.classList.add('scale-95', 'opacity-0');\n setTimeout(() => {\n menu.classList.add('hidden');\n }, 100);\n }\n }\n \n function confirmBulkDelete() {\n if (selectedFiles.size === 0) return;\n showConfirmDialog('media-bulk-delete-confirm');\n }\n\n async function performBulkDelete() {\n if (selectedFiles.size === 0) return;\n\n try {\n // Show loading state\n const btn = document.getElementById('bulk-actions-btn');\n const originalText = btn.innerHTML;\n btn.innerHTML = 'Deleting...';\n btn.disabled = true;\n\n // Hide menu\n const menu = document.getElementById('bulk-actions-menu');\n menu.classList.remove('scale-100', 'opacity-100');\n menu.classList.add('scale-95', 'opacity-0');\n setTimeout(() => menu.classList.add('hidden'), 100);\n \n const response = await fetch('/api/media/bulk-delete', {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n fileIds: Array.from(selectedFiles)\n })\n });\n \n const result = await response.json();\n \n if (result.success) {\n // Show success notification\n showNotification(\\`Successfully deleted \\${result.summary.successful} file\\${result.summary.successful > 1 ? 's' : ''}\\`, 'success');\n \n // Remove deleted files from DOM\n result.deleted.forEach(item => {\n const element = document.querySelector(\\`[data-file-id=\"\\${item.fileId}\"]\\`);\n if (element) {\n element.remove();\n }\n });\n \n // Show errors if any\n if (result.errors.length > 0) {\n console.warn('Some files failed to delete:', result.errors);\n showNotification(\\`\\${result.errors.length} file\\${result.errors.length > 1 ? 's' : ''} failed to delete\\`, 'warning');\n }\n \n // Clear selection\n selectedFiles.clear();\n updateBulkActionsButton();\n document.getElementById('select-all-btn').textContent = 'Select All';\n } else {\n showNotification('Failed to delete files', 'error');\n }\n } catch (error) {\n console.error('Bulk delete error:', error);\n showNotification('An error occurred while deleting files', 'error');\n } finally {\n // Reset button state\n updateBulkActionsButton();\n }\n }\n \n function openMoveToFolderModal() {\n if (selectedFiles.size === 0) return;\n\n // Update file count in modal\n document.getElementById('move-file-count').textContent = selectedFiles.size.toString();\n\n // Show modal\n document.getElementById('move-to-folder-modal').classList.remove('hidden');\n\n // Hide bulk actions menu\n const menu = document.getElementById('bulk-actions-menu');\n menu.classList.remove('scale-100', 'opacity-100');\n menu.classList.add('scale-95', 'opacity-0');\n setTimeout(() => menu.classList.add('hidden'), 100);\n }\n\n function closeMoveToFolderModal() {\n document.getElementById('move-to-folder-modal').classList.add('hidden');\n }\n\n function openCreateFolderModal() {\n document.getElementById('create-folder-modal').classList.remove('hidden');\n // Clear and focus the input\n const input = document.getElementById('folder-name');\n input.value = '';\n setTimeout(() => input.focus(), 100);\n }\n\n function closeCreateFolderModal() {\n document.getElementById('create-folder-modal').classList.add('hidden');\n }\n\n async function createNewFolder(event) {\n event.preventDefault();\n\n const folderName = document.getElementById('folder-name').value.trim();\n\n if (!folderName) {\n showNotification('Please enter a folder name', 'error');\n return;\n }\n\n // Validate folder name format\n const folderPattern = /^[a-z0-9-_]+$/;\n if (!folderPattern.test(folderName)) {\n showNotification('Folder name can only contain lowercase letters, numbers, hyphens, and underscores', 'error');\n return;\n }\n\n try {\n const response = await fetch('/api/media/create-folder', {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({ folderName })\n });\n\n const result = await response.json();\n\n if (result.success) {\n showNotification(\\`Folder \"\\${folderName}\" created successfully\\`, 'success');\n closeCreateFolderModal();\n\n // Reload the page to show the new folder (delay to allow notification to show)\n setTimeout(() => {\n window.location.reload();\n }, 2000);\n } else {\n showNotification(result.error || 'Failed to create folder', 'error');\n }\n } catch (error) {\n console.error('Create folder error:', error);\n showNotification('An error occurred while creating the folder', 'error');\n }\n }\n\n async function performBulkMove(targetFolder) {\n if (selectedFiles.size === 0) return;\n\n try {\n // Show loading state\n closeMoveToFolderModal();\n const btn = document.getElementById('bulk-actions-btn');\n const originalText = btn.innerHTML;\n btn.innerHTML = 'Moving...';\n btn.disabled = true;\n\n const response = await fetch('/api/media/bulk-move', {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n fileIds: Array.from(selectedFiles),\n folder: targetFolder\n })\n });\n\n const result = await response.json();\n\n if (result.success) {\n // Show success notification\n const movedCount = result.summary.successful;\n showNotification(\\`Successfully moved \\${movedCount} file\\${movedCount > 1 ? 's' : ''} to \\${targetFolder}\\`, 'success');\n\n // Reload the page to show updated file locations\n setTimeout(() => {\n window.location.reload();\n }, 1000);\n } else {\n showNotification('Failed to move files', 'error');\n updateBulkActionsButton();\n }\n } catch (error) {\n console.error('Bulk move error:', error);\n showNotification('An error occurred while moving files', 'error');\n updateBulkActionsButton();\n }\n }\n\n function showNotification(message, type = 'info') {\n const notification = document.createElement('div');\n const bgColor = type === 'success' ? 'bg-green-600' :\n type === 'warning' ? 'bg-yellow-600' :\n type === 'error' ? 'bg-red-600' : 'bg-blue-600';\n\n notification.className = \\`fixed top-4 right-4 \\${bgColor} text-white px-4 py-3 rounded-lg shadow-xl ring-1 ring-white/10 z-50 transition-all transform translate-x-full\\`;\n notification.textContent = message;\n document.body.appendChild(notification);\n\n // Animate in\n setTimeout(() => {\n notification.classList.remove('translate-x-full');\n }, 100);\n\n // Remove after 3 seconds\n setTimeout(() => {\n notification.classList.add('translate-x-full');\n setTimeout(() => {\n if (document.body.contains(notification)) {\n document.body.removeChild(notification);\n }\n }, 300);\n }, 3000);\n }\n \n // URL parameter helpers\n function updateUrlParam(param, value) {\n const url = new URL(window.location);\n url.searchParams.set(param, value);\n return url.toString();\n }\n \n // Drag and drop handling\n const uploadZone = document.getElementById('upload-zone');\n \n ['dragenter', 'dragover', 'dragleave', 'drop'].forEach(eventName => {\n uploadZone.addEventListener(eventName, preventDefaults, false);\n });\n \n function preventDefaults(e) {\n e.preventDefault();\n e.stopPropagation();\n }\n \n ['dragenter', 'dragover'].forEach(eventName => {\n uploadZone.addEventListener(eventName, () => uploadZone.classList.add('dragover'), false);\n });\n \n ['dragleave', 'drop'].forEach(eventName => {\n uploadZone.addEventListener(eventName, () => uploadZone.classList.remove('dragover'), false);\n });\n \n uploadZone.addEventListener('drop', handleDrop, false);\n \n function handleDrop(e) {\n const dt = e.dataTransfer;\n const files = dt.files;\n handleFileSelect(files);\n }\n \n function handleFileSelect(files) {\n dragDropFiles = Array.from(files);\n \n // Update the actual file input with the selected files\n const fileInput = document.getElementById('file-input');\n const dt = new DataTransfer();\n dragDropFiles.forEach(file => dt.items.add(file));\n fileInput.files = dt.files;\n \n displaySelectedFiles();\n document.getElementById('upload-btn').disabled = false;\n }\n \n function displaySelectedFiles() {\n const fileList = document.getElementById('file-list');\n const selectedFilesDiv = document.getElementById('selected-files');\n\n selectedFilesDiv.innerHTML = '';\n\n dragDropFiles.forEach((file, index) => {\n const fileItem = document.createElement('div');\n fileItem.className = 'flex items-center justify-between p-2 rounded-lg bg-zinc-50 dark:bg-zinc-800 ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10';\n fileItem.innerHTML = \\`\n <div class=\"flex items-center space-x-2\">\n <span class=\"text-sm text-zinc-950 dark:text-white\">\\${file.name}</span>\n <span class=\"text-xs text-zinc-500 dark:text-zinc-400\">(\\${formatFileSize(file.size)})</span>\n </div>\n <button onclick=\"removeFile(\\${index})\" class=\"text-red-600 dark:text-red-400 hover:text-red-700 dark:hover:text-red-300 transition-colors\">\n <svg class=\"w-4 h-4\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M6 18L18 6M6 6l12 12\"></path>\n </svg>\n </button>\n \\`;\n selectedFilesDiv.appendChild(fileItem);\n });\n\n fileList.classList.toggle('hidden', dragDropFiles.length === 0);\n }\n \n function removeFile(index) {\n dragDropFiles.splice(index, 1);\n displaySelectedFiles();\n \n const fileInput = document.getElementById('file-input');\n const dt = new DataTransfer();\n dragDropFiles.forEach(file => dt.items.add(file));\n fileInput.files = dt.files;\n \n document.getElementById('upload-btn').disabled = dragDropFiles.length === 0;\n }\n \n function formatFileSize(bytes) {\n if (bytes === 0) return '0 Bytes';\n const k = 1024;\n const sizes = ['Bytes', 'KB', 'MB', 'GB'];\n const i = Math.floor(Math.log(bytes) / Math.log(k));\n return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];\n }\n \n // Copy to clipboard function\n function copyToClipboard(text) {\n navigator.clipboard.writeText(text).then(() => {\n const notification = document.createElement('div');\n notification.className = 'fixed top-4 right-4 bg-green-600 text-white px-4 py-3 rounded-lg shadow-xl ring-1 ring-white/10 z-50';\n notification.textContent = 'URL copied to clipboard!';\n document.body.appendChild(notification);\n setTimeout(() => document.body.removeChild(notification), 2000);\n }).catch(err => {\n console.error('Failed to copy: ', err);\n });\n }\n\n // Toggle clear button visibility\n function toggleMediaClearButton() {\n const searchInput = document.getElementById('media-search-input');\n const clearButton = document.getElementById('clear-media-search');\n if (searchInput.value.trim()) {\n clearButton.classList.remove('hidden');\n } else {\n clearButton.classList.add('hidden');\n }\n }\n\n // Clear search input\n function clearMediaSearch() {\n const searchInput = document.getElementById('media-search-input');\n searchInput.value = '';\n toggleMediaClearButton();\n // Trigger htmx to refresh the grid\n htmx.trigger(searchInput, 'keyup');\n }\n\n // Initialize clear button visibility on page load\n document.addEventListener('DOMContentLoaded', function() {\n toggleMediaClearButton();\n });\n\n // Close modal when clicking outside\n document.getElementById('file-modal').addEventListener('click', function(e) {\n if (e.target === this) {\n this.classList.add('hidden');\n }\n });\n \n // Close bulk actions dropdown when clicking outside\n document.addEventListener('click', function(e) {\n const dropdown = document.getElementById('bulk-actions-dropdown');\n const menu = document.getElementById('bulk-actions-menu');\n if (dropdown && menu && !dropdown.contains(e.target)) {\n menu.classList.remove('scale-100', 'opacity-100');\n menu.classList.add('scale-95', 'opacity-0');\n setTimeout(() => {\n menu.classList.add('hidden');\n }, 100);\n }\n });\n </script>\n\n <!-- Confirmation Dialog for Bulk Delete -->\n ${renderConfirmationDialog({\n id: \"media-bulk-delete-confirm\",\n title: \"Delete Selected Files\",\n message: `Are you sure you want to delete ${\n data.files.length > 0 ? \"the selected files\" : \"these files\"\n }? This action cannot be undone and the files will be permanently removed.`,\n confirmText: \"Delete Files\",\n cancelText: \"Cancel\",\n confirmClass: \"bg-red-500 hover:bg-red-400\",\n iconColor: \"red\",\n onConfirm: \"performBulkDelete()\",\n })}\n\n <!-- Confirmation Dialog Script -->\n ${getConfirmationDialogScript()}\n `;\n\n function buildPageUrl(page: number, folder: string, type: string): string {\n const params = new URLSearchParams();\n params.set(\"page\", page.toString());\n if (folder !== \"all\") params.set(\"folder\", folder);\n if (type !== \"all\") params.set(\"type\", type);\n return `/admin/media?${params.toString()}`;\n }\n\n const layoutData: AdminLayoutCatalystData = {\n title: \"Media Library\",\n pageTitle: \"Media Library\",\n currentPath: \"/admin/media\",\n user: data.user,\n version: data.version,\n content: pageContent,\n };\n\n return renderAdminLayoutCatalyst(layoutData);\n}\n","import { MediaFile } from './media-grid.template'\n\nexport interface MediaFileDetailsData {\n file: MediaFile & {\n width?: number\n height?: number\n folder: string\n uploadedAt: string\n }\n}\n\nexport function renderMediaFileDetails(data: MediaFileDetailsData): string {\n const { file } = data\n \n return `\n <div class=\"flex justify-between items-center mb-4\">\n <h3 class=\"text-lg font-semibold text-zinc-950 dark:text-white\">File Details</h3>\n <button onclick=\"document.getElementById('file-modal').classList.add('hidden')\" class=\"text-zinc-500 dark:text-zinc-400 hover:text-zinc-950 dark:hover:text-white transition-colors\">\n <svg class=\"w-6 h-6\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M6 18L18 6M6 6l12 12\"></path>\n </svg>\n </button>\n </div>\n \n <div class=\"grid grid-cols-1 lg:grid-cols-2 gap-6\">\n <!-- Preview -->\n <div class=\"space-y-4\">\n <div class=\"rounded-xl bg-zinc-50 dark:bg-zinc-800 p-4\">\n ${file.isImage ? `\n <img src=\"${file.public_url}\" alt=\"${file.alt || file.filename}\" class=\"w-full h-auto rounded-lg\">\n ` : file.isVideo ? `\n <video src=\"${file.public_url}\" controls class=\"w-full h-auto rounded-lg\"></video>\n ` : `\n <div class=\"flex items-center justify-center h-32\">\n <svg class=\"w-12 h-12 text-zinc-400\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z\"></path>\n </svg>\n </div>\n `}\n </div>\n\n <div class=\"text-center space-x-2\">\n <button\n onclick=\"copyToClipboard('${file.public_url}')\"\n class=\"inline-flex items-center rounded-lg bg-blue-600 px-4 py-2 text-sm font-semibold text-white hover:bg-blue-700 transition-colors\"\n >\n Copy URL\n </button>\n <a\n href=\"${file.public_url}\"\n target=\"_blank\"\n class=\"inline-flex items-center rounded-lg bg-white dark:bg-zinc-800 px-4 py-2 text-sm font-semibold text-zinc-950 dark:text-white ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 hover:bg-zinc-50 dark:hover:bg-zinc-700 transition-colors\"\n >\n Open Original\n </a>\n </div>\n </div>\n \n <!-- Details -->\n <div class=\"space-y-4\">\n <div>\n <label class=\"block text-sm font-medium text-zinc-950 dark:text-white mb-1\">Filename</label>\n <p class=\"text-sm text-zinc-500 dark:text-zinc-400\">${file.original_name}</p>\n </div>\n\n <div class=\"grid grid-cols-2 gap-4\">\n <div>\n <label class=\"block text-sm font-medium text-zinc-950 dark:text-white mb-1\">Size</label>\n <p class=\"text-sm text-zinc-500 dark:text-zinc-400\">${file.fileSize}</p>\n </div>\n <div>\n <label class=\"block text-sm font-medium text-zinc-950 dark:text-white mb-1\">Type</label>\n <p class=\"text-sm text-zinc-500 dark:text-zinc-400\">${file.mime_type}</p>\n </div>\n </div>\n\n ${file.width && file.height ? `\n <div class=\"grid grid-cols-2 gap-4\">\n <div>\n <label class=\"block text-sm font-medium text-zinc-950 dark:text-white mb-1\">Width</label>\n <p class=\"text-sm text-zinc-500 dark:text-zinc-400\">${file.width}px</p>\n </div>\n <div>\n <label class=\"block text-sm font-medium text-zinc-950 dark:text-white mb-1\">Height</label>\n <p class=\"text-sm text-zinc-500 dark:text-zinc-400\">${file.height}px</p>\n </div>\n </div>\n ` : ''}\n\n <div>\n <label class=\"block text-sm font-medium text-zinc-950 dark:text-white mb-1\">Folder</label>\n <p class=\"text-sm text-zinc-500 dark:text-zinc-400\">${file.folder}</p>\n </div>\n\n <div>\n <label class=\"block text-sm font-medium text-zinc-950 dark:text-white mb-1\">Uploaded</label>\n <p class=\"text-sm text-zinc-500 dark:text-zinc-400\">${file.uploadedAt}</p>\n </div>\n\n <!-- Editable Fields -->\n <form hx-put=\"/admin/media/${file.id}\" hx-target=\"#file-modal-content\" class=\"space-y-4\">\n <div>\n <label class=\"block text-sm font-medium text-zinc-950 dark:text-white mb-1\">Alt Text</label>\n <input\n type=\"text\"\n name=\"alt\"\n value=\"${file.alt || ''}\"\n class=\"w-full rounded-lg bg-white dark:bg-zinc-800 px-3 py-2 text-sm text-zinc-950 dark:text-white placeholder-zinc-500 dark:placeholder-zinc-400 ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 focus:ring-2 focus:ring-blue-600 dark:focus:ring-blue-500 focus:outline-none transition-colors\"\n placeholder=\"Describe this image...\"\n >\n </div>\n\n <div>\n <label class=\"block text-sm font-medium text-zinc-950 dark:text-white mb-1\">Caption</label>\n <textarea\n name=\"caption\"\n rows=\"3\"\n class=\"w-full rounded-lg bg-white dark:bg-zinc-800 px-3 py-2 text-sm text-zinc-950 dark:text-white placeholder-zinc-500 dark:placeholder-zinc-400 ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 focus:ring-2 focus:ring-blue-600 dark:focus:ring-blue-500 focus:outline-none transition-colors\"\n placeholder=\"Optional caption...\"\n >${file.caption || ''}</textarea>\n </div>\n\n <div>\n <label class=\"block text-sm font-medium text-zinc-950 dark:text-white mb-1\">Tags</label>\n <input\n type=\"text\"\n name=\"tags\"\n value=\"${file.tags.join(', ')}\"\n class=\"w-full rounded-lg bg-white dark:bg-zinc-800 px-3 py-2 text-sm text-zinc-950 dark:text-white placeholder-zinc-500 dark:placeholder-zinc-400 ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 focus:ring-2 focus:ring-blue-600 dark:focus:ring-blue-500 focus:outline-none transition-colors\"\n placeholder=\"tag1, tag2, tag3\"\n >\n </div>\n\n <div class=\"flex justify-between\">\n <button\n type=\"submit\"\n class=\"rounded-lg bg-green-600 px-4 py-2 text-sm font-semibold text-white hover:bg-green-700 transition-colors\"\n >\n Save Changes\n </button>\n <button\n type=\"button\"\n hx-delete=\"/admin/media/${file.id}\"\n hx-confirm=\"Are you sure you want to delete this file?\"\n hx-target=\"body\"\n class=\"rounded-lg bg-red-600 px-4 py-2 text-sm font-semibold text-white hover:bg-red-700 transition-colors\"\n >\n Delete File\n </button>\n </div>\n </form>\n </div>\n </div>\n `\n}","import { Hono } from 'hono'\nimport { html, raw } from 'hono/html'\nimport { z } from 'zod'\nimport type { D1Database, KVNamespace, R2Bucket } from '@cloudflare/workers-types'\nimport { requireAuth, requireRole } from '../middleware'\nimport { renderMediaLibraryPage, MediaLibraryPageData, FolderStats, TypeStats } from '../templates/pages/admin-media-library.template'\nimport { renderMediaFileDetails, MediaFileDetailsData } from '../templates/components/media-file-details.template'\nimport { MediaFile, renderMediaFileCard } from '../templates/components/media-grid.template'\nimport type { Bindings, Variables } from '../app'\n\n// File validation schema\nconst fileValidationSchema = z.object({\n name: z.string().min(1).max(255),\n type: z.string().refine(\n (type) => {\n const allowedTypes = [\n // Images\n 'image/jpeg', 'image/jpg', 'image/png', 'image/gif', 'image/webp', 'image/svg+xml',\n // Documents\n 'application/pdf', 'text/plain', 'application/msword', \n 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',\n // Videos\n 'video/mp4', 'video/webm', 'video/ogg', 'video/avi', 'video/mov',\n // Audio\n 'audio/mp3', 'audio/wav', 'audio/ogg', 'audio/m4a'\n ]\n return allowedTypes.includes(type)\n },\n { message: 'Unsupported file type' }\n ),\n size: z.number().min(1).max(50 * 1024 * 1024) // 50MB max\n})\n\nconst adminMediaRoutes = new Hono<{ Bindings: Bindings; Variables: Variables }>()\n\n// Apply authentication middleware\nadminMediaRoutes.use('*', requireAuth())\n\n// Media library main page\nadminMediaRoutes.get('/', async (c) => {\n try {\n const user = c.get('user')\n const { searchParams } = new URL(c.req.url)\n const folder = searchParams.get('folder') || 'all'\n const type = searchParams.get('type') || 'all'\n const view = searchParams.get('view') || 'grid'\n const page = parseInt(searchParams.get('page') || '1')\n const ____cacheBust = searchParams.get('t') // Cache-busting parameter\n const limit = 24\n const offset = (page - 1) * limit\n\n const db = c.env.DB\n\n // TODO: Cache implementation removed during migration - will be added back when cache plugin is migrated\n\n // Build query for media files\n let query = 'SELECT * FROM media'\n const params: any[] = []\n const conditions: string[] = ['deleted_at IS NULL']\n \n if (folder !== 'all') {\n conditions.push('folder = ?')\n params.push(folder)\n }\n \n if (type !== 'all') {\n switch (type) {\n case 'images':\n conditions.push('mime_type LIKE ?')\n params.push('image/%')\n break\n case 'documents':\n conditions.push('mime_type IN (?, ?, ?)')\n params.push('application/pdf', 'text/plain', 'application/msword')\n break\n case 'videos':\n conditions.push('mime_type LIKE ?')\n params.push('video/%')\n break\n }\n }\n \n if (conditions.length > 0) {\n query += ` WHERE ${conditions.join(' AND ')}`\n }\n \n query += ` ORDER BY uploaded_at DESC LIMIT ${limit} OFFSET ${offset}`\n \n const stmt = db.prepare(query)\n const { results } = await stmt.bind(...params).all()\n \n // Get folder statistics\n const foldersStmt = db.prepare(`\n SELECT folder, COUNT(*) as count, SUM(size) as totalSize\n FROM media\n WHERE deleted_at IS NULL\n GROUP BY folder\n ORDER BY folder\n `)\n const { results: folders } = await foldersStmt.all()\n \n // Get type statistics\n const typesStmt = db.prepare(`\n SELECT\n CASE\n WHEN mime_type LIKE 'image/%' THEN 'images'\n WHEN mime_type LIKE 'video/%' THEN 'videos'\n WHEN mime_type IN ('application/pdf', 'text/plain') THEN 'documents'\n ELSE 'other'\n END as type,\n COUNT(*) as count\n FROM media\n WHERE deleted_at IS NULL\n GROUP BY type\n `)\n const { results: types } = await typesStmt.all()\n \n // Process media files with local serving URLs\n const mediaFiles: MediaFile[] = results.map((row: any) => ({\n id: row.id,\n filename: row.filename,\n original_name: row.original_name,\n mime_type: row.mime_type,\n size: row.size,\n public_url: `/files/${row.r2_key}`,\n thumbnail_url: row.mime_type.startsWith('image/') ? `/files/${row.r2_key}` : undefined,\n alt: row.alt,\n caption: row.caption,\n tags: row.tags ? JSON.parse(row.tags) : [],\n uploaded_at: row.uploaded_at,\n fileSize: formatFileSize(row.size),\n uploadedAt: new Date(row.uploaded_at).toLocaleDateString(),\n isImage: row.mime_type.startsWith('image/'),\n isVideo: row.mime_type.startsWith('video/'),\n isDocument: !row.mime_type.startsWith('image/') && !row.mime_type.startsWith('video/')\n }))\n \n const pageData: MediaLibraryPageData = {\n files: mediaFiles,\n folders: folders.map((f: any) => ({\n folder: f.folder,\n count: f.count,\n totalSize: f.totalSize\n })) as FolderStats[],\n types: types.map((t: any) => ({\n type: t.type,\n count: t.count\n })) as TypeStats[],\n currentFolder: folder,\n currentType: type,\n currentView: view as 'grid' | 'list',\n currentPage: page,\n totalFiles: results.length,\n hasNextPage: results.length === limit,\n user: {\n name: user!.email,\n email: user!.email,\n role: user!.role\n },\n version: c.get('appVersion')\n }\n\n // TODO: Cache implementation removed during migration\n\n return c.html(renderMediaLibraryPage(pageData))\n } catch (error) {\n console.error('Error loading media library:', error)\n return c.html(html`<p>Error loading media library</p>`)\n }\n})\n\n// Media selector endpoint (HTMX endpoint for content form media selection)\nadminMediaRoutes.get('/selector', async (c) => {\n try {\n const { searchParams } = new URL(c.req.url)\n const search = searchParams.get('search') || ''\n const db = c.env.DB\n\n // Build search query\n let query = 'SELECT * FROM media WHERE deleted_at IS NULL'\n const params: any[] = []\n\n if (search.trim()) {\n query += ' AND (filename LIKE ? OR original_name LIKE ? OR alt LIKE ?)'\n const searchTerm = `%${search}%`\n params.push(searchTerm, searchTerm, searchTerm)\n }\n\n query += ' ORDER BY uploaded_at DESC LIMIT 24'\n\n const stmt = db.prepare(query)\n const { results } = await stmt.bind(...params).all()\n\n const mediaFiles = results.map((row: any) => ({\n id: row.id,\n filename: row.filename,\n original_name: row.original_name,\n mime_type: row.mime_type,\n size: row.size,\n public_url: `/files/${row.r2_key}`,\n thumbnail_url: row.mime_type.startsWith('image/') ? `/files/${row.r2_key}` : undefined,\n alt: row.alt,\n tags: row.tags ? JSON.parse(row.tags) : [],\n uploaded_at: row.uploaded_at,\n fileSize: formatFileSize(row.size),\n uploadedAt: new Date(row.uploaded_at).toLocaleDateString(),\n isImage: row.mime_type.startsWith('image/'),\n isVideo: row.mime_type.startsWith('video/'),\n isDocument: !row.mime_type.startsWith('image/') && !row.mime_type.startsWith('video/')\n }))\n\n // Render media selector grid\n return c.html(html`\n <div class=\"mb-4\">\n <input\n type=\"search\"\n id=\"media-selector-search\"\n placeholder=\"Search files...\"\n class=\"w-full rounded-lg bg-white dark:bg-zinc-800 px-4 py-2 text-sm text-zinc-950 dark:text-white shadow-sm ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 placeholder:text-zinc-400 dark:placeholder:text-zinc-500 focus:outline-none focus:ring-2 focus:ring-zinc-950 dark:focus:ring-white transition-shadow\"\n hx-get=\"/admin/media/selector\"\n hx-trigger=\"keyup changed delay:300ms\"\n hx-target=\"#media-selector-grid\"\n hx-include=\"[name='search']\"\n >\n </div>\n\n <div id=\"media-selector-grid\" class=\"grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 gap-4 max-h-96 overflow-y-auto\">\n ${raw(mediaFiles.map(file => `\n <div\n class=\"relative group cursor-pointer rounded-lg overflow-hidden bg-zinc-50 dark:bg-zinc-800 shadow-sm hover:shadow-md transition-shadow\"\n data-media-id=\"${file.id}\"\n >\n <div class=\"aspect-square relative\">\n ${file.isImage ? `\n <img\n src=\"${file.public_url}\"\n alt=\"${file.alt || file.filename}\"\n class=\"w-full h-full object-cover\"\n loading=\"lazy\"\n >\n ` : file.isVideo ? `\n <video\n src=\"${file.public_url}\"\n class=\"w-full h-full object-cover\"\n muted\n ></video>\n ` : `\n <div class=\"w-full h-full flex items-center justify-center bg-zinc-100 dark:bg-zinc-700\">\n <div class=\"text-center\">\n <svg class=\"w-12 h-12 mx-auto text-zinc-400 dark:text-zinc-500\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z\"></path>\n </svg>\n <span class=\"text-xs text-zinc-500 dark:text-zinc-400 mt-1\">${file.filename.split('.').pop()?.toUpperCase()}</span>\n </div>\n </div>\n `}\n\n <div class=\"absolute inset-0 bg-black/50 opacity-0 group-hover:opacity-100 transition-opacity flex items-center justify-center\">\n <button\n type=\"button\"\n onclick=\"selectMediaFile('${file.id}', '${file.public_url.replace(/'/g, \"\\\\'\")}', '${file.filename.replace(/'/g, \"\\\\'\")}')\"\n class=\"px-4 py-2 bg-white dark:bg-zinc-900 text-zinc-950 dark:text-white rounded-lg font-medium hover:bg-zinc-100 dark:hover:bg-zinc-800 transition-colors\"\n >\n Select\n </button>\n </div>\n </div>\n\n <div class=\"p-2\">\n <p class=\"text-xs text-zinc-700 dark:text-zinc-300 truncate\" title=\"${file.original_name}\">\n ${file.original_name}\n </p>\n <p class=\"text-xs text-zinc-500 dark:text-zinc-400\">\n ${file.fileSize}\n </p>\n </div>\n </div>\n `).join(''))}\n </div>\n\n ${mediaFiles.length === 0 ? html`\n <div class=\"text-center py-12 text-zinc-500 dark:text-zinc-400\">\n <svg class=\"mx-auto h-12 w-12 text-zinc-400 dark:text-zinc-500\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z\"></path>\n </svg>\n <p class=\"mt-2\">No media files found</p>\n </div>\n ` : ''}\n `)\n } catch (error) {\n console.error('Error loading media selector:', error)\n return c.html(html`<div class=\"text-red-500 dark:text-red-400\">Error loading media files</div>`)\n }\n})\n\n// Search media files (HTMX endpoint)\nadminMediaRoutes.get('/search', async (c) => {\n try {\n const { searchParams } = new URL(c.req.url)\n const search = searchParams.get('search') || ''\n const folder = searchParams.get('folder') || 'all'\n const type = searchParams.get('type') || 'all'\n const db = c.env.DB\n \n // Build search query\n let query = 'SELECT * FROM media'\n const params: any[] = []\n const conditions: string[] = []\n \n if (search.trim()) {\n conditions.push('(filename LIKE ? OR original_name LIKE ? OR alt LIKE ?)')\n const searchTerm = `%${search}%`\n params.push(searchTerm, searchTerm, searchTerm)\n }\n \n if (folder !== 'all') {\n conditions.push('folder = ?')\n params.push(folder)\n }\n \n if (type !== 'all') {\n switch (type) {\n case 'images':\n conditions.push('mime_type LIKE ?')\n params.push('image/%')\n break\n case 'documents':\n conditions.push('mime_type IN (?, ?, ?)')\n params.push('application/pdf', 'text/plain', 'application/msword')\n break\n case 'videos':\n conditions.push('mime_type LIKE ?')\n params.push('video/%')\n break\n }\n }\n \n if (conditions.length > 0) {\n query += ` WHERE ${conditions.join(' AND ')}`\n }\n \n query += ` ORDER BY uploaded_at DESC LIMIT 24`\n \n const stmt = db.prepare(query)\n const { results } = await stmt.bind(...params).all()\n \n const mediaFiles = results.map((row: any) => ({\n ...row,\n public_url: `/files/${row.r2_key}`,\n thumbnail_url: row.mime_type.startsWith('image/') ? `/files/${row.r2_key}` : undefined,\n tags: row.tags ? JSON.parse(row.tags) : [],\n uploadedAt: new Date(row.uploaded_at).toLocaleDateString(),\n fileSize: formatFileSize(row.size),\n isImage: row.mime_type.startsWith('image/'),\n isVideo: row.mime_type.startsWith('video/'),\n isDocument: !row.mime_type.startsWith('image/') && !row.mime_type.startsWith('video/')\n }))\n \n const gridHTML = mediaFiles.map(file => generateMediaItemHTML(file)).join('')\n \n return c.html(raw(gridHTML))\n } catch (error) {\n console.error('Error searching media:', error)\n return c.html('<div class=\"text-red-500\">Error searching files</div>')\n }\n})\n\n// Get file details modal (HTMX endpoint)\nadminMediaRoutes.get('/:id/details', async (c) => {\n try {\n const id = c.req.param('id')\n const db = c.env.DB\n \n const stmt = db.prepare('SELECT * FROM media WHERE id = ?')\n const result = await stmt.bind(id).first() as any\n \n if (!result) {\n return c.html('<div class=\"text-red-500\">File not found</div>')\n }\n \n const file: MediaFile & { width?: number; height?: number; folder: string; uploadedAt: string } = {\n id: result.id,\n filename: result.filename,\n original_name: result.original_name,\n mime_type: result.mime_type,\n size: result.size,\n public_url: `/files/${result.r2_key}`,\n thumbnail_url: result.mime_type.startsWith('image/') ? `/files/${result.r2_key}` : undefined,\n alt: result.alt,\n caption: result.caption,\n tags: result.tags ? JSON.parse(result.tags) : [],\n uploaded_at: result.uploaded_at,\n fileSize: formatFileSize(result.size),\n uploadedAt: new Date(result.uploaded_at).toLocaleString(),\n isImage: result.mime_type.startsWith('image/'),\n isVideo: result.mime_type.startsWith('video/'),\n isDocument: !result.mime_type.startsWith('image/') && !result.mime_type.startsWith('video/'),\n width: result.width,\n height: result.height,\n folder: result.folder\n }\n \n const detailsData: MediaFileDetailsData = { file }\n \n return c.html(renderMediaFileDetails(detailsData))\n } catch (error) {\n console.error('Error fetching file details:', error)\n return c.html('<div class=\"text-red-500\">Error loading file details</div>')\n }\n})\n\n// Upload files endpoint (HTMX compatible)\nadminMediaRoutes.post('/upload', async (c) => {\n try {\n const user = c.get('user')\n const formData = await c.req.formData()\n const fileEntries = formData.getAll('files') as unknown[]\n const files: File[] = []\n\n for (const entry of fileEntries) {\n if (entry instanceof File) {\n files.push(entry)\n }\n }\n \n if (!files || files.length === 0) {\n return c.html(html`\n <div class=\"bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded\">\n No files provided\n </div>\n `)\n }\n\n const uploadResults = []\n const errors = []\n\n // Check if MEDIA_BUCKET is available\n console.log('[MEDIA UPLOAD] c.env keys:', Object.keys(c.env))\n console.log('[MEDIA UPLOAD] MEDIA_BUCKET defined?', !!c.env.MEDIA_BUCKET)\n console.log('[MEDIA UPLOAD] MEDIA_BUCKET type:', typeof c.env.MEDIA_BUCKET)\n\n if (!c.env.MEDIA_BUCKET) {\n console.error('[MEDIA UPLOAD] MEDIA_BUCKET is not available! Available env keys:', Object.keys(c.env))\n return c.html(html`\n <div class=\"bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded\">\n Media storage (R2) is not configured. Please check your wrangler.toml configuration.\n <br><small>Debug: Available bindings: ${Object.keys(c.env).join(', ')}</small>\n </div>\n `)\n }\n\n for (const file of files) {\n try {\n // Validate file\n const validation = fileValidationSchema.safeParse({\n name: file.name,\n type: file.type,\n size: file.size\n })\n\n if (!validation.success) {\n errors.push({\n filename: file.name,\n error: validation.error.issues[0]?.message || 'Validation failed'\n })\n continue\n }\n\n // Generate unique filename and R2 key\n const fileId = crypto.randomUUID()\n const fileExtension = file.name.split('.').pop() || ''\n const filename = `${fileId}.${fileExtension}`\n const folder = formData.get('folder') as string || 'uploads'\n const r2Key = `${folder}/${filename}`\n\n // Upload to R2\n const arrayBuffer = await file.arrayBuffer()\n const uploadResult = await c.env.MEDIA_BUCKET.put(r2Key, arrayBuffer, {\n httpMetadata: {\n contentType: file.type,\n contentDisposition: `inline; filename=\"${file.name}\"`\n },\n customMetadata: {\n originalName: file.name,\n uploadedBy: user!.userId,\n uploadedAt: new Date().toISOString()\n }\n })\n\n if (!uploadResult) {\n errors.push({\n filename: file.name,\n error: 'Failed to upload to storage'\n })\n continue\n }\n\n // Extract image dimensions if it's an image\n let width: number | undefined\n let height: number | undefined\n \n if (file.type.startsWith('image/') && !file.type.includes('svg')) {\n try {\n const dimensions = await getImageDimensions(arrayBuffer)\n width = dimensions.width\n height = dimensions.height\n } catch (error) {\n console.warn('Failed to extract image dimensions:', error)\n }\n }\n\n // Generate URLs - use public serving route\n const publicUrl = `/files/${r2Key}`\n const thumbnailUrl = file.type.startsWith('image/') ? publicUrl : undefined\n\n // Save to database\n const stmt = c.env.DB.prepare(`\n INSERT INTO media (\n id, filename, original_name, mime_type, size, width, height, \n folder, r2_key, public_url, thumbnail_url, uploaded_by, uploaded_at\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n `)\n \n await stmt.bind(\n fileId,\n filename,\n file.name,\n file.type,\n file.size,\n width,\n height,\n folder,\n r2Key,\n publicUrl,\n thumbnailUrl,\n user!.userId,\n Math.floor(Date.now() / 1000)\n ).run()\n\n uploadResults.push({\n id: fileId,\n filename: filename,\n originalName: file.name,\n mimeType: file.type,\n size: file.size,\n publicUrl: publicUrl\n })\n } catch (error) {\n errors.push({\n filename: file.name,\n error: 'Upload failed: ' + (error instanceof Error ? error.message : 'Unknown error')\n })\n }\n }\n\n // TODO: Cache invalidation removed during migration\n\n // Fetch updated media list to include in response\n let mediaGridHTML = ''\n if (uploadResults.length > 0) {\n try {\n const folderEntry = formData.get('folder')\n const folder = typeof folderEntry === 'string' ? folderEntry : 'uploads'\n const query = 'SELECT * FROM media WHERE deleted_at IS NULL ORDER BY uploaded_at DESC LIMIT 24'\n const stmt = c.env.DB.prepare(query)\n const { results } = await stmt.all()\n\n const mediaFiles = results.map((row: any) => ({\n id: row.id,\n filename: row.filename,\n original_name: row.original_name,\n mime_type: row.mime_type,\n size: row.size,\n public_url: `/files/${row.r2_key}`,\n thumbnail_url: row.mime_type.startsWith('image/') ? `/files/${row.r2_key}` : undefined,\n tags: row.tags ? JSON.parse(row.tags) : [],\n uploaded_at: row.uploaded_at,\n fileSize: formatFileSize(row.size),\n uploadedAt: new Date(row.uploaded_at).toLocaleDateString(),\n isImage: row.mime_type.startsWith('image/'),\n isVideo: row.mime_type.startsWith('video/'),\n isDocument: !row.mime_type.startsWith('image/') && !row.mime_type.startsWith('video/')\n }))\n\n mediaGridHTML = mediaFiles.map(file => renderMediaFileCard(file, 'grid', true)).join('')\n } catch (error) {\n console.error('Error fetching updated media list:', error)\n }\n }\n\n // Return HTMX response with results\n return c.html(html`\n ${uploadResults.length > 0 ? html`\n <div class=\"bg-green-100 border border-green-400 text-green-700 px-4 py-3 rounded mb-4\">\n Successfully uploaded ${uploadResults.length} file${uploadResults.length > 1 ? 's' : ''}\n </div>\n ` : ''}\n\n ${errors.length > 0 ? html`\n <div class=\"bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded\">\n <p class=\"font-medium\">Upload errors:</p>\n <ul class=\"list-disc list-inside mt-2\">\n ${errors.map(error => html`\n <li>${error.filename}: ${error.error}</li>\n `)}\n </ul>\n </div>\n ` : ''}\n\n ${uploadResults.length > 0 ? html`\n <script>\n // Close modal and refresh page after successful upload with cache busting\n setTimeout(() => {\n document.getElementById('upload-modal').classList.add('hidden');\n window.location.href = '/admin/media?t=' + Date.now();\n }, 1500);\n </script>\n ` : ''}\n `)\n } catch (error) {\n console.error('Upload error:', error)\n return c.html(html`\n <div class=\"bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded\">\n Upload failed: ${error instanceof Error ? error.message : 'Unknown error'}\n </div>\n `)\n }\n})\n\n// Serve files from R2 storage\nadminMediaRoutes.get('/file/*', async (c) => {\n try {\n const r2Key = c.req.path.replace('/admin/media/file/', '')\n \n if (!r2Key) {\n return c.notFound()\n }\n\n // Get file from R2\n const object = await c.env.MEDIA_BUCKET.get(r2Key)\n \n if (!object) {\n return c.notFound()\n }\n\n // Set appropriate headers\n const headers = new Headers()\n object.httpMetadata?.contentType && headers.set('Content-Type', object.httpMetadata.contentType)\n object.httpMetadata?.contentDisposition && headers.set('Content-Disposition', object.httpMetadata.contentDisposition)\n headers.set('Cache-Control', 'public, max-age=31536000') // 1 year cache\n \n return new Response(object.body as any, {\n headers\n })\n } catch (error) {\n console.error('Error serving file:', error)\n return c.notFound()\n }\n})\n\n// Update media file metadata (HTMX compatible)\nadminMediaRoutes.put('/:id', async (c) => {\n try {\n const user = c.get('user')\n const fileId = c.req.param('id')\n const formData = await c.req.formData()\n \n // Get file record\n const stmt = c.env.DB.prepare('SELECT * FROM media WHERE id = ? AND deleted_at IS NULL')\n const fileRecord = await stmt.bind(fileId).first() as any\n \n if (!fileRecord) {\n return c.html(html`\n <div class=\"bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded mb-4\">\n File not found\n </div>\n `)\n }\n\n // Check permissions (only allow updates by uploader or admin)\n if (fileRecord.uploaded_by !== user!.userId && user!.role !== 'admin') {\n return c.html(html`\n <div class=\"bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded mb-4\">\n Permission denied\n </div>\n `)\n }\n\n // Extract form data\n const alt = formData.get('alt') as string || null\n const caption = formData.get('caption') as string || null\n const tagsString = formData.get('tags') as string || ''\n const tags = tagsString ? tagsString.split(',').map(tag => tag.trim()).filter(tag => tag) : []\n\n // Update database\n const updateStmt = c.env.DB.prepare(`\n UPDATE media \n SET alt = ?, caption = ?, tags = ?, updated_at = ?\n WHERE id = ?\n `)\n await updateStmt.bind(\n alt,\n caption,\n JSON.stringify(tags),\n Math.floor(Date.now() / 1000),\n fileId\n ).run()\n\n // TODO: Cache invalidation removed during migration\n\n return c.html(html`\n <div class=\"bg-green-100 border border-green-400 text-green-700 px-4 py-3 rounded mb-4\">\n File updated successfully\n </div>\n <script>\n // Refresh the file details\n setTimeout(() => {\n htmx.trigger('#file-modal-content', 'htmx:load');\n }, 1000);\n </script>\n `)\n } catch (error) {\n console.error('Update error:', error)\n return c.html(html`\n <div class=\"bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded mb-4\">\n Update failed: ${error instanceof Error ? error.message : 'Unknown error'}\n </div>\n `)\n }\n})\n\n// Cleanup unused media files (HTMX compatible)\nadminMediaRoutes.delete('/cleanup', requireRole('admin'), async (c) => {\n try {\n const db = c.env.DB\n\n // Find all media files\n const allMediaStmt = db.prepare('SELECT id, r2_key, filename FROM media WHERE deleted_at IS NULL')\n const { results: allMedia } = await allMediaStmt.all<{ id: string; r2_key: string; filename: string }>()\n\n // Find media files referenced in content\n // Content can reference media in various JSON fields like data, hero_image, etc.\n const contentStmt = db.prepare('SELECT data FROM content')\n const { results: contentRecords } = await contentStmt.all<{ data: unknown }>()\n\n // Extract all media URLs from content\n const referencedUrls = new Set<string>()\n for (const record of contentRecords || []) {\n if (record.data) {\n const dataStr = typeof record.data === 'string' ? record.data : JSON.stringify(record.data)\n // Find all /files/ URLs in the content\n const urlMatches = dataStr.matchAll(/\\/files\\/([^\\s\"',]+)/g)\n for (const match of urlMatches) {\n referencedUrls.add(match[1]!)\n }\n }\n }\n\n // Find unreferenced media files\n const mediaRows = allMedia || []\n const unusedFiles = mediaRows.filter((file) => !referencedUrls.has(file.r2_key))\n\n if (unusedFiles.length === 0) {\n return c.html(html`\n <div class=\"bg-blue-100 border border-blue-400 text-blue-700 px-4 py-3 rounded\">\n No unused media files found. All files are referenced in content.\n </div>\n <script>\n setTimeout(() => {\n window.location.href = '/admin/media?t=' + Date.now();\n }, 2000);\n </script>\n `)\n }\n\n // Delete unused files from R2 and database\n let deletedCount = 0\n const errors = []\n\n for (const file of unusedFiles) {\n try {\n // Delete from R2\n await c.env.MEDIA_BUCKET.delete(file.r2_key)\n\n // Soft delete in database\n const deleteStmt = db.prepare('UPDATE media SET deleted_at = ? WHERE id = ?')\n await deleteStmt.bind(Math.floor(Date.now() / 1000), file.id).run()\n\n deletedCount++\n } catch (error) {\n console.error(`Failed to delete ${file.filename}:`, error)\n errors.push({\n filename: file.filename,\n error: error instanceof Error ? error.message : 'Unknown error'\n })\n }\n }\n\n // Return success response\n return c.html(html`\n <div class=\"bg-green-100 border border-green-400 text-green-700 px-4 py-3 rounded mb-4\">\n Successfully cleaned up ${deletedCount} unused media file${deletedCount !== 1 ? 's' : ''}.\n ${errors.length > 0 ? html`\n <br><span class=\"text-sm\">Failed to delete ${errors.length} file${errors.length !== 1 ? 's' : ''}.</span>\n ` : ''}\n </div>\n\n ${errors.length > 0 ? html`\n <div class=\"bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded\">\n <p class=\"font-medium\">Cleanup errors:</p>\n <ul class=\"list-disc list-inside mt-2 text-sm\">\n ${errors.map(error => html`\n <li>${error.filename}: ${error.error}</li>\n `)}\n </ul>\n </div>\n ` : ''}\n\n <script>\n // Refresh media library after cleanup\n setTimeout(() => {\n window.location.href = '/admin/media?t=' + Date.now();\n }, 2500);\n </script>\n `)\n } catch (error) {\n console.error('Cleanup error:', error)\n return c.html(html`\n <div class=\"bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded\">\n Cleanup failed: ${error instanceof Error ? error.message : 'Unknown error'}\n </div>\n `)\n }\n})\n\n// Delete media file (HTMX compatible)\nadminMediaRoutes.delete('/:id', async (c) => {\n try {\n const user = c.get('user')\n const fileId = c.req.param('id')\n\n // Get file record\n const stmt = c.env.DB.prepare('SELECT * FROM media WHERE id = ? AND deleted_at IS NULL')\n const fileRecord = await stmt.bind(fileId).first() as any\n\n if (!fileRecord) {\n return c.html(html`\n <div class=\"bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded mb-4\">\n File not found\n </div>\n `)\n }\n\n // Check permissions (only allow deletion by uploader or admin)\n if (fileRecord.uploaded_by !== user!.userId && user!.role !== 'admin') {\n return c.html(html`\n <div class=\"bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded mb-4\">\n Permission denied\n </div>\n `)\n }\n\n // Delete from R2\n try {\n await c.env.MEDIA_BUCKET.delete(fileRecord.r2_key)\n } catch (error) {\n console.warn('Failed to delete from R2:', error)\n // Continue with database deletion even if R2 deletion fails\n }\n\n // Soft delete in database\n const deleteStmt = c.env.DB.prepare('UPDATE media SET deleted_at = ? WHERE id = ?')\n await deleteStmt.bind(Math.floor(Date.now() / 1000), fileId).run()\n\n // TODO: Cache invalidation removed during migration\n\n // Return HTMX response that redirects to media library\n return c.html(html`\n <script>\n // Close modal if open\n const modal = document.getElementById('file-modal');\n if (modal) {\n modal.classList.add('hidden');\n }\n // Redirect to media library\n window.location.href = '/admin/media';\n </script>\n `)\n } catch (error) {\n console.error('Delete error:', error)\n return c.html(html`\n <div class=\"bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded mb-4\">\n Delete failed: ${error instanceof Error ? error.message : 'Unknown error'}\n </div>\n `)\n }\n})\n\n// Helper function to extract image dimensions\nasync function getImageDimensions(arrayBuffer: ArrayBuffer): Promise<{ width: number; height: number }> {\n const uint8Array = new Uint8Array(arrayBuffer)\n \n // Check for JPEG\n if (uint8Array[0] === 0xFF && uint8Array[1] === 0xD8) {\n return getJPEGDimensions(uint8Array)\n }\n \n // Check for PNG\n if (uint8Array[0] === 0x89 && uint8Array[1] === 0x50 && uint8Array[2] === 0x4E && uint8Array[3] === 0x47) {\n return getPNGDimensions(uint8Array)\n }\n \n // Default fallback\n return { width: 0, height: 0 }\n}\n\nfunction getJPEGDimensions(uint8Array: Uint8Array): { width: number; height: number } {\n let i = 2\n while (i < uint8Array.length - 8) {\n if (uint8Array[i] === 0xFF && uint8Array[i + 1] === 0xC0) {\n return {\n height: (uint8Array[i + 5]! << 8) | uint8Array[i + 6]!,\n width: (uint8Array[i + 7]! << 8) | uint8Array[i + 8]!\n }\n }\n const segmentLength = (uint8Array[i + 2]! << 8) | uint8Array[i + 3]!\n i += 2 + segmentLength\n }\n return { width: 0, height: 0 }\n}\n\nfunction getPNGDimensions(uint8Array: Uint8Array): { width: number; height: number } {\n if (uint8Array.length < 24) {\n return { width: 0, height: 0 }\n }\n return {\n width: (uint8Array[16]! << 24) | (uint8Array[17]! << 16) | (uint8Array[18]! << 8) | uint8Array[19]!,\n height: (uint8Array[20]! << 24) | (uint8Array[21]! << 16) | (uint8Array[22]! << 8) | uint8Array[23]!\n }\n}\n\n// Helper function to generate media item HTML\nfunction generateMediaItemHTML(file: any): string {\n const isImage = file.isImage\n const isVideo = file.isVideo\n \n return `\n <div \n class=\"media-item bg-white rounded-lg shadow-sm overflow-hidden cursor-pointer\" \n data-file-id=\"${file.id}\"\n onclick=\"toggleFileSelection('${file.id}')\"\n >\n <div class=\"aspect-square relative\">\n ${isImage ? `\n <img \n src=\"${file.public_url}\" \n alt=\"${file.alt || file.filename}\"\n class=\"w-full h-full object-cover\"\n loading=\"lazy\"\n >\n ` : isVideo ? `\n <video \n src=\"${file.public_url}\" \n class=\"w-full h-full object-cover\"\n muted\n ></video>\n ` : `\n <div class=\"w-full h-full flex items-center justify-center bg-gray-100\">\n <div class=\"text-center\">\n <svg class=\"file-icon mx-auto text-gray-400\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z\"></path>\n </svg>\n <span class=\"text-xs text-gray-500 mt-1\">${file.filename.split('.').pop()?.toUpperCase()}</span>\n </div>\n </div>\n `}\n \n <div class=\"preview-overlay flex items-center justify-center\">\n <div class=\"flex space-x-2\">\n <button \n onclick=\"event.stopPropagation(); showFileDetails('${file.id}')\"\n class=\"p-2 bg-white bg-opacity-20 rounded-full hover:bg-opacity-30\"\n >\n <svg class=\"w-5 h-5 text-white\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M15 12a3 3 0 11-6 0 3 3 0 016 0z\"></path>\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z\"></path>\n </svg>\n </button>\n <button \n onclick=\"event.stopPropagation(); copyToClipboard('${file.public_url}')\"\n class=\"p-2 bg-white bg-opacity-20 rounded-full hover:bg-opacity-30\"\n >\n <svg class=\"w-5 h-5 text-white\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z\"></path>\n </svg>\n </button>\n </div>\n </div>\n </div>\n \n <div class=\"p-3\">\n <h4 class=\"text-sm font-medium text-gray-900 truncate\" title=\"${file.original_name}\">\n ${file.original_name}\n </h4>\n <div class=\"flex justify-between items-center mt-1\">\n <span class=\"text-xs text-gray-500\">${file.fileSize}</span>\n <span class=\"text-xs text-gray-500\">${file.uploadedAt}</span>\n </div>\n ${file.tags.length > 0 ? `\n <div class=\"flex flex-wrap gap-1 mt-2\">\n ${file.tags.slice(0, 2).map((tag: string) => `\n <span class=\"inline-block px-2 py-1 text-xs bg-gray-100 text-gray-600 rounded\">\n ${tag}\n </span>\n `).join('')}\n ${file.tags.length > 2 ? `<span class=\"text-xs text-gray-400\">+${file.tags.length - 2}</span>` : ''}\n </div>\n ` : ''}\n </div>\n </div>\n `\n}\n\n// Helper function to format file size\nfunction formatFileSize(bytes: number): string {\n if (bytes === 0) return '0 Bytes'\n const k = 1024\n const sizes = ['Bytes', 'KB', 'MB', 'GB']\n const i = Math.floor(Math.log(bytes) / Math.log(k))\n return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]\n}\n\nexport { adminMediaRoutes }\n","import { renderAdminLayoutCatalyst, AdminLayoutCatalystData } from '../layouts/admin-layout-catalyst.template'\nimport { renderConfirmationDialog, getConfirmationDialogScript } from '../components/confirmation-dialog.template'\n\nexport interface Plugin {\n id: string\n name: string\n displayName: string\n description: string\n version: string\n author: string\n status: 'active' | 'inactive' | 'error' | 'uninstalled'\n category: string\n icon: string\n downloadCount?: number\n rating?: number\n lastUpdated: string\n dependencies?: string[]\n permissions?: string[]\n isCore?: boolean\n}\n\nexport interface PluginsListPageData {\n plugins: Plugin[]\n stats?: {\n total: number\n active: number\n inactive: number\n errors: number\n uninstalled: number\n }\n user?: {\n name: string\n email: string\n role: string\n }\n version?: string\n}\n\nexport function renderPluginsListPage(data: PluginsListPageData): string {\n const pageContent = `\n <div>\n <!-- Header -->\n <div class=\"flex flex-col sm:flex-row sm:items-center sm:justify-between mb-6\">\n <div>\n <h1 class=\"text-2xl/8 font-semibold text-zinc-950 dark:text-white sm:text-xl/8\">Plugins</h1>\n <p class=\"mt-2 text-sm/6 text-zinc-500 dark:text-zinc-400\">Manage and extend functionality with plugins</p>\n </div>\n </div>\n\n <!-- Experimental Notice -->\n <div class=\"mb-6 rounded-lg bg-amber-50 dark:bg-amber-900/20 border border-amber-200 dark:border-amber-800/50 p-4\">\n <div class=\"flex items-start\">\n <div class=\"flex-shrink-0\">\n <svg class=\"h-5 w-5 text-amber-600 dark:text-amber-400\" viewBox=\"0 0 20 20\" fill=\"currentColor\">\n <path fill-rule=\"evenodd\" d=\"M8.485 2.495c.673-1.167 2.357-1.167 3.03 0l6.28 10.875c.673 1.167-.17 2.625-1.516 2.625H3.72c-1.347 0-2.189-1.458-1.515-2.625L8.485 2.495zM10 5a.75.75 0 01.75.75v3.5a.75.75 0 01-1.5 0v-3.5A.75.75 0 0110 5zm0 9a1 1 0 100-2 1 1 0 000 2z\" clip-rule=\"evenodd\" />\n </svg>\n </div>\n <div class=\"ml-3 flex-1\">\n <h3 class=\"text-sm font-semibold text-amber-800 dark:text-amber-200\">\n Experimental Feature\n </h3>\n <div class=\"mt-2 text-sm text-amber-700 dark:text-amber-300\">\n <p>\n Plugin management is currently under active development. While functional, some features may change or have limitations.\n Please report any issues you encounter on our <a href=\"https://discord.gg/8bMy6bv3sZ\" target=\"_blank\" class=\"font-medium underline hover:text-amber-900 dark:hover:text-amber-100\">Discord community</a>.\n </p>\n </div>\n </div>\n </div>\n </div>\n\n <!-- Stats -->\n <div class=\"mb-6\">\n <h3 class=\"text-base font-semibold text-zinc-950 dark:text-white\">Plugin Statistics</h3>\n <dl class=\"mt-5 grid grid-cols-1 divide-zinc-950/5 dark:divide-white/10 overflow-hidden rounded-lg bg-zinc-800/75 dark:bg-zinc-800/75 ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 md:grid-cols-5 md:divide-x md:divide-y-0\">\n <div class=\"px-4 py-5 sm:p-6\">\n <dt class=\"text-base font-normal text-zinc-700 dark:text-zinc-100\">Total Plugins</dt>\n <dd class=\"mt-1 flex items-baseline justify-between md:block lg:flex\">\n <div class=\"flex items-baseline text-2xl font-semibold text-cyan-400\">\n ${data.stats?.total || 0}\n </div>\n <div class=\"inline-flex items-baseline rounded-full bg-lime-400/10 text-lime-600 dark:text-lime-400 px-2.5 py-0.5 text-sm font-medium md:mt-2 lg:mt-0\">\n <svg viewBox=\"0 0 20 20\" fill=\"currentColor\" class=\"-ml-1 mr-0.5 size-5 shrink-0 self-center\">\n <path d=\"M10 17a.75.75 0 0 1-.75-.75V5.612L5.29 9.77a.75.75 0 0 1-1.08-1.04l5.25-5.5a.75.75 0 0 1 1.08 0l5.25 5.5a.75.75 0 1 1-1.08 1.04l-3.96-4.158V16.25A.75.75 0 0 1 10 17Z\" clip-rule=\"evenodd\" fill-rule=\"evenodd\" />\n </svg>\n <span class=\"sr-only\">Increased by</span>\n 8.5%\n </div>\n </dd>\n </div>\n <div class=\"px-4 py-5 sm:p-6\">\n <dt class=\"text-base font-normal text-zinc-700 dark:text-zinc-100\">Active Plugins</dt>\n <dd class=\"mt-1 flex items-baseline justify-between md:block lg:flex\">\n <div class=\"flex items-baseline text-2xl font-semibold text-lime-400\">\n ${data.stats?.active || 0}\n </div>\n <div class=\"inline-flex items-baseline rounded-full bg-lime-400/10 text-lime-600 dark:text-lime-400 px-2.5 py-0.5 text-sm font-medium md:mt-2 lg:mt-0\">\n <svg viewBox=\"0 0 20 20\" fill=\"currentColor\" class=\"-ml-1 mr-0.5 size-5 shrink-0 self-center\">\n <path d=\"M10 17a.75.75 0 0 1-.75-.75V5.612L5.29 9.77a.75.75 0 0 1-1.08-1.04l5.25-5.5a.75.75 0 0 1 1.08 0l5.25 5.5a.75.75 0 1 1-1.08 1.04l-3.96-4.158V16.25A.75.75 0 0 1 10 17Z\" clip-rule=\"evenodd\" fill-rule=\"evenodd\" />\n </svg>\n <span class=\"sr-only\">Increased by</span>\n 12.3%\n </div>\n </dd>\n </div>\n <div class=\"px-4 py-5 sm:p-6\">\n <dt class=\"text-base font-normal text-zinc-700 dark:text-zinc-100\">Inactive Plugins</dt>\n <dd class=\"mt-1 flex items-baseline justify-between md:block lg:flex\">\n <div class=\"flex items-baseline text-2xl font-semibold text-purple-400\">\n ${data.stats?.inactive || 0}\n </div>\n <div class=\"inline-flex items-baseline rounded-full bg-pink-400/10 text-pink-600 dark:text-pink-400 px-2.5 py-0.5 text-sm font-medium md:mt-2 lg:mt-0\">\n <svg viewBox=\"0 0 20 20\" fill=\"currentColor\" class=\"-ml-1 mr-0.5 size-5 shrink-0 self-center\">\n <path d=\"M10 3a.75.75 0 0 1 .75.75v10.638l3.96-4.158a.75.75 0 1 1 1.08 1.04l-5.25 5.5a.75.75 0 0 1-1.08 0l-5.25-5.5a.75.75 0 1 1 1.08-1.04l3.96 4.158V3.75A.75.75 0 0 1 10 3Z\" clip-rule=\"evenodd\" fill-rule=\"evenodd\" />\n </svg>\n <span class=\"sr-only\">Decreased by</span>\n 3.2%\n </div>\n </dd>\n </div>\n <div class=\"px-4 py-5 sm:p-6\">\n <dt class=\"text-base font-normal text-zinc-700 dark:text-zinc-100\">Plugin Errors</dt>\n <dd class=\"mt-1 flex items-baseline justify-between md:block lg:flex\">\n <div class=\"flex items-baseline text-2xl font-semibold text-pink-400\">\n ${data.stats?.errors || 0}\n </div>\n <div class=\"inline-flex items-baseline rounded-full bg-pink-400/10 text-pink-600 dark:text-pink-400 px-2.5 py-0.5 text-sm font-medium md:mt-2 lg:mt-0\">\n <svg viewBox=\"0 0 20 20\" fill=\"currentColor\" class=\"-ml-1 mr-0.5 size-5 shrink-0 self-center\">\n <path d=\"M10 3a.75.75 0 0 1 .75.75v10.638l3.96-4.158a.75.75 0 1 1 1.08 1.04l-5.25 5.5a.75.75 0 0 1-1.08 0l-5.25-5.5a.75.75 0 1 1 1.08-1.04l3.96 4.158V3.75A.75.75 0 0 1 10 3Z\" clip-rule=\"evenodd\" fill-rule=\"evenodd\" />\n </svg>\n <span class=\"sr-only\">Decreased by</span>\n 1.5%\n </div>\n </dd>\n </div>\n <div class=\"px-4 py-5 sm:p-6\">\n <dt class=\"text-base font-normal text-zinc-700 dark:text-zinc-100\">Available to Install</dt>\n <dd class=\"mt-1 flex items-baseline justify-between md:block lg:flex\">\n <div class=\"flex items-baseline text-2xl font-semibold text-zinc-400\">\n ${data.stats?.uninstalled || 0}\n </div>\n <div class=\"inline-flex items-baseline rounded-full bg-zinc-400/10 text-zinc-600 dark:text-zinc-400 px-2.5 py-0.5 text-sm font-medium md:mt-2 lg:mt-0\">\n <svg viewBox=\"0 0 20 20\" fill=\"currentColor\" class=\"-ml-1 mr-0.5 size-5 shrink-0 self-center\">\n <path d=\"M10.75 4.75a.75.75 0 00-1.5 0v4.5h-4.5a.75.75 0 000 1.5h4.5v4.5a.75.75 0 001.5 0v-4.5h4.5a.75.75 0 000-1.5h-4.5v-4.5z\" />\n </svg>\n <span class=\"sr-only\">Available</span>\n Ready\n </div>\n </dd>\n </div>\n </dl>\n </div>\n\n <!-- Filters -->\n <div class=\"relative rounded-xl overflow-hidden mb-6\">\n <!-- Gradient Background -->\n <div class=\"absolute inset-0 bg-gradient-to-r from-cyan-500/10 via-blue-500/10 to-purple-500/10 dark:from-cyan-400/20 dark:via-blue-400/20 dark:to-purple-400/20\"></div>\n\n <div class=\"relative bg-white/80 dark:bg-zinc-900/80 backdrop-blur-xl shadow-sm ring-1 ring-zinc-950/5 dark:ring-white/10\">\n <div class=\"px-6 py-5\">\n <div class=\"flex items-center justify-between\">\n <div class=\"flex items-center space-x-4 flex-1\">\n <div>\n <label class=\"block text-sm/6 font-medium text-zinc-950 dark:text-white\">Category</label>\n <div class=\"mt-2 grid grid-cols-1\">\n <select id=\"category-filter\" onchange=\"filterPlugins()\" class=\"col-start-1 row-start-1 w-full appearance-none rounded-md bg-white/5 dark:bg-white/5 py-1.5 pl-3 pr-8 text-base text-zinc-950 dark:text-white outline outline-1 -outline-offset-1 outline-cyan-500/30 dark:outline-cyan-400/30 *:bg-white dark:*:bg-zinc-800 focus-visible:outline focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-cyan-500 dark:focus-visible:outline-cyan-400 sm:text-sm/6 min-w-48\">\n <option value=\"\">All Categories</option>\n <option value=\"content\">Content Management</option>\n <option value=\"media\">Media</option>\n <option value=\"seo\">SEO & Analytics</option>\n <option value=\"security\">Security</option>\n <option value=\"utilities\">Utilities</option>\n <option value=\"system\">System</option>\n <option value=\"development\">Development</option>\n <option value=\"demo\">Demo</option>\n </select>\n <svg viewBox=\"0 0 16 16\" fill=\"currentColor\" data-slot=\"icon\" aria-hidden=\"true\" class=\"pointer-events-none col-start-1 row-start-1 mr-2 size-5 self-center justify-self-end text-cyan-600 dark:text-cyan-400 sm:size-4\">\n <path d=\"M4.22 6.22a.75.75 0 0 1 1.06 0L8 8.94l2.72-2.72a.75.75 0 1 1 1.06 1.06l-3.25 3.25a.75.75 0 0 1-1.06 0L4.22 7.28a.75.75 0 0 1 0-1.06Z\" clip-rule=\"evenodd\" fill-rule=\"evenodd\" />\n </svg>\n </div>\n </div>\n <div>\n <label class=\"block text-sm/6 font-medium text-zinc-950 dark:text-white\">Status</label>\n <div class=\"mt-2 grid grid-cols-1\">\n <select id=\"status-filter\" onchange=\"filterPlugins()\" class=\"col-start-1 row-start-1 w-full appearance-none rounded-md bg-white/5 dark:bg-white/5 py-1.5 pl-3 pr-8 text-base text-zinc-950 dark:text-white outline outline-1 -outline-offset-1 outline-cyan-500/30 dark:outline-cyan-400/30 *:bg-white dark:*:bg-zinc-800 focus-visible:outline focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-cyan-500 dark:focus-visible:outline-cyan-400 sm:text-sm/6 min-w-48\">\n <option value=\"\">All Status</option>\n <option value=\"active\">Active</option>\n <option value=\"inactive\">Inactive</option>\n <option value=\"uninstalled\">Available to Install</option>\n <option value=\"error\">Error</option>\n </select>\n <svg viewBox=\"0 0 16 16\" fill=\"currentColor\" data-slot=\"icon\" aria-hidden=\"true\" class=\"pointer-events-none col-start-1 row-start-1 mr-2 size-5 self-center justify-self-end text-cyan-600 dark:text-cyan-400 sm:size-4\">\n <path d=\"M4.22 6.22a.75.75 0 0 1 1.06 0L8 8.94l2.72-2.72a.75.75 0 1 1 1.06 1.06l-3.25 3.25a.75.75 0 0 1-1.06 0L4.22 7.28a.75.75 0 0 1 0-1.06Z\" clip-rule=\"evenodd\" fill-rule=\"evenodd\" />\n </svg>\n </div>\n </div>\n <div class=\"flex-1 max-w-md\">\n <label class=\"block text-sm font-medium text-zinc-950 dark:text-white mb-2\">Search</label>\n <div class=\"relative group\">\n <div class=\"absolute left-3.5 top-2.5 flex items-center justify-center w-5 h-5 rounded-full bg-gradient-to-br from-cyan-400 to-blue-500 dark:from-cyan-300 dark:to-blue-400 opacity-90 group-focus-within:opacity-100 transition-opacity\">\n <svg class=\"h-3 w-3 text-white\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\" stroke-width=\"2.5\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z\"/>\n </svg>\n </div>\n <input\n id=\"search-input\"\n type=\"text\"\n placeholder=\"Search plugins...\"\n oninput=\"filterPlugins()\"\n class=\"w-full rounded-full bg-transparent px-11 py-2 text-sm text-zinc-950 dark:text-white placeholder-zinc-500 dark:placeholder-zinc-400 border-2 border-cyan-200/50 dark:border-cyan-700/50 focus:outline-none focus:border-cyan-500 dark:focus:border-cyan-400 focus:shadow-lg focus:shadow-cyan-500/20 dark:focus:shadow-cyan-400/20 transition-all duration-300\"\n />\n </div>\n </div>\n </div>\n <div class=\"flex items-center gap-x-3 ml-4\">\n <button\n onclick=\"location.reload()\"\n class=\"inline-flex items-center gap-x-1.5 px-3 py-1.5 bg-white/90 dark:bg-zinc-800/90 backdrop-blur-sm text-zinc-950 dark:text-white text-sm font-medium rounded-full ring-1 ring-inset ring-cyan-200/50 dark:ring-cyan-700/50 hover:bg-gradient-to-r hover:from-cyan-50 hover:to-blue-50 dark:hover:from-cyan-900/30 dark:hover:to-blue-900/30 hover:ring-cyan-300 dark:hover:ring-cyan-600 transition-all duration-200\"\n >\n <svg class=\"h-4 w-4\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15\"/>\n </svg>\n Refresh\n </button>\n </div>\n </div>\n </div>\n </div>\n </div>\n\n <!-- Plugins Grid -->\n <div id=\"plugins-grid\" class=\"grid grid-cols-1 md:grid-cols-2 xl:grid-cols-3 gap-6\">\n ${data.plugins.map(plugin => renderPluginCard(plugin)).join('')}\n </div>\n\n <script>\n async function togglePlugin(pluginId, action) {\n const button = event.target;\n const originalText = button.textContent;\n button.disabled = true;\n button.textContent = action === 'activate' ? 'Activating...' : 'Deactivating...';\n \n try {\n const response = await fetch(\\`/admin/plugins/\\${pluginId}/\\${action}\\`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json'\n }\n });\n \n const result = await response.json();\n \n if (result.success) {\n // Update UI\n const card = button.closest('.plugin-card');\n const statusBadge = card.querySelector('.status-badge');\n\n if (action === 'activate') {\n // Update status badge\n statusBadge.className = 'status-badge inline-flex items-center rounded-md px-2.5 py-1 text-sm font-medium ring-1 ring-inset bg-lime-50 dark:bg-lime-500/10 text-lime-700 dark:text-lime-300 ring-lime-700/10 dark:ring-lime-400/20';\n statusBadge.innerHTML = '<div class=\"w-2 h-2 bg-lime-500 dark:bg-lime-400 rounded-full mr-2\"></div>Active';\n // Update card border to green\n card.className = 'plugin-card rounded-xl bg-white dark:bg-zinc-900 shadow-sm ring-[3px] ring-lime-500 dark:ring-lime-400 p-6 hover:bg-zinc-50 dark:hover:bg-zinc-800/50 transition-all';\n // Update button\n button.textContent = 'Deactivate';\n button.onclick = () => togglePlugin(pluginId, 'deactivate');\n button.className = 'bg-red-600 dark:bg-red-700 hover:bg-red-700 dark:hover:bg-red-600 text-white px-3 py-1.5 rounded-lg text-sm font-medium transition-colors';\n } else {\n // Update status badge\n statusBadge.className = 'status-badge inline-flex items-center rounded-md px-2.5 py-1 text-sm font-medium ring-1 ring-inset bg-zinc-50 dark:bg-zinc-500/10 text-zinc-700 dark:text-zinc-400 ring-zinc-700/10 dark:ring-zinc-400/20';\n statusBadge.innerHTML = '<div class=\"w-2 h-2 bg-zinc-500 dark:bg-zinc-400 rounded-full mr-2\"></div>Inactive';\n // Update card border to pink\n card.className = 'plugin-card rounded-xl bg-white dark:bg-zinc-900 shadow-sm ring-[3px] ring-pink-500 dark:ring-pink-400 p-6 hover:bg-zinc-50 dark:hover:bg-zinc-800/50 transition-all';\n // Update button\n button.textContent = 'Activate';\n button.onclick = () => togglePlugin(pluginId, 'activate');\n button.className = 'bg-lime-600 dark:bg-lime-700 hover:bg-lime-700 dark:hover:bg-lime-600 text-white px-3 py-1.5 rounded-lg text-sm font-medium transition-colors';\n }\n\n showNotification(\\`Plugin \\${action}d successfully\\`, 'success');\n } else {\n throw new Error(result.error || \\`Failed to \\${action} plugin\\`);\n }\n } catch (error) {\n showNotification(error.message, 'error');\n button.textContent = originalText;\n } finally {\n button.disabled = false;\n }\n }\n \n async function installPlugin(pluginName) {\n const button = event.target;\n button.disabled = true;\n button.textContent = 'Installing...';\n \n try {\n const response = await fetch('/admin/plugins/install', {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json'\n },\n body: JSON.stringify({ name: pluginName })\n });\n \n const result = await response.json();\n \n if (result.success) {\n showNotification('Plugin installed successfully!', 'success');\n setTimeout(() => location.reload(), 1500);\n } else {\n throw new Error(result.error || 'Failed to install plugin');\n }\n } catch (error) {\n showNotification(error.message, 'error');\n button.disabled = false;\n button.textContent = 'Install';\n }\n }\n \n let pluginToUninstall = null;\n\n async function uninstallPlugin(pluginId) {\n pluginToUninstall = pluginId;\n showConfirmDialog('uninstall-plugin-confirm');\n }\n\n async function performUninstallPlugin() {\n if (!pluginToUninstall) return;\n\n const button = event.target;\n if (button) button.disabled = true;\n\n try {\n const response = await fetch(\\`/admin/plugins/\\${pluginToUninstall}/uninstall\\`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json'\n }\n });\n\n const result = await response.json();\n\n if (result.success) {\n showNotification('Plugin uninstalled successfully!', 'success');\n setTimeout(() => location.reload(), 1500);\n } else {\n throw new Error(result.error || 'Failed to uninstall plugin');\n }\n } catch (error) {\n showNotification(error.message, 'error');\n if (button) button.disabled = false;\n } finally {\n pluginToUninstall = null;\n }\n }\n \n function openPluginSettings(pluginId) {\n // Email plugin has a custom settings page\n if (pluginId === 'email') {\n window.location.href = '/admin/plugins/email/settings';\n } else {\n window.location.href = \\`/admin/plugins/\\${pluginId}\\`;\n }\n }\n \n function showPluginDetails(pluginId) {\n // TODO: Implement plugin details modal\n showNotification('Plugin details coming soon!', 'info');\n }\n \n function showNotification(message, type) {\n const notification = document.createElement('div');\n const bgColor = type === 'success' ? 'bg-green-600' : type === 'error' ? 'bg-red-600' : 'bg-blue-600';\n notification.className = \\`fixed top-4 right-4 px-4 py-2 rounded-lg text-white z-50 \\${bgColor}\\`;\n notification.textContent = message;\n document.body.appendChild(notification);\n\n setTimeout(() => {\n notification.remove();\n }, 3000);\n }\n\n function filterPlugins() {\n const categoryFilter = document.getElementById('category-filter').value.toLowerCase();\n const statusFilter = document.getElementById('status-filter').value.toLowerCase();\n const searchInput = document.getElementById('search-input').value.toLowerCase();\n\n const pluginCards = document.querySelectorAll('.plugin-card');\n let visibleCount = 0;\n\n pluginCards.forEach(card => {\n // Get plugin data from card attributes\n const category = card.getAttribute('data-category')?.toLowerCase() || '';\n const status = card.getAttribute('data-status')?.toLowerCase() || '';\n const name = card.getAttribute('data-name')?.toLowerCase() || '';\n const description = card.getAttribute('data-description')?.toLowerCase() || '';\n\n // Check if plugin matches all filters\n let matches = true;\n\n // Category filter\n if (categoryFilter && category !== categoryFilter) {\n matches = false;\n }\n\n // Status filter\n if (statusFilter && status !== statusFilter) {\n matches = false;\n }\n\n // Search filter - check if search term is in name or description\n if (searchInput && !name.includes(searchInput) && !description.includes(searchInput)) {\n matches = false;\n }\n\n // Show/hide card\n if (matches) {\n card.style.display = '';\n visibleCount++;\n } else {\n card.style.display = 'none';\n }\n });\n\n // Show/hide \"no results\" message\n let noResultsMsg = document.getElementById('no-results-message');\n if (visibleCount === 0) {\n if (!noResultsMsg) {\n noResultsMsg = document.createElement('div');\n noResultsMsg.id = 'no-results-message';\n noResultsMsg.className = 'col-span-full text-center py-12';\n noResultsMsg.innerHTML = \\`\n <div class=\"flex flex-col items-center\">\n <svg class=\"w-16 h-16 text-zinc-400 dark:text-zinc-600 mb-4\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M9.172 16.172a4 4 0 015.656 0M9 10h.01M15 10h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z\" />\n </svg>\n <h3 class=\"text-lg font-semibold text-zinc-950 dark:text-white mb-2\">No plugins found</h3>\n <p class=\"text-sm text-zinc-500 dark:text-zinc-400\">Try adjusting your filters or search terms</p>\n </div>\n \\`;\n document.getElementById('plugins-grid').appendChild(noResultsMsg);\n }\n noResultsMsg.style.display = '';\n } else if (noResultsMsg) {\n noResultsMsg.style.display = 'none';\n }\n }\n </script>\n\n <!-- Confirmation Dialogs -->\n ${renderConfirmationDialog({\n id: 'uninstall-plugin-confirm',\n title: 'Uninstall Plugin',\n message: 'Are you sure you want to uninstall this plugin? This action cannot be undone.',\n confirmText: 'Uninstall',\n cancelText: 'Cancel',\n iconColor: 'red',\n confirmClass: 'bg-red-500 hover:bg-red-400',\n onConfirm: 'performUninstallPlugin()'\n })}\n\n ${getConfirmationDialogScript()}\n `\n\n const layoutData: AdminLayoutCatalystData = {\n title: 'Plugins',\n pageTitle: 'Plugin Management',\n currentPath: '/admin/plugins',\n user: data.user,\n version: data.version,\n content: pageContent\n }\n\n return renderAdminLayoutCatalyst(layoutData)\n}\n\nfunction renderPluginCard(plugin: Plugin): string {\n const statusColors = {\n active: 'bg-lime-50 dark:bg-lime-500/10 text-lime-700 dark:text-lime-300 ring-lime-700/10 dark:ring-lime-400/20',\n inactive: 'bg-zinc-50 dark:bg-zinc-500/10 text-zinc-700 dark:text-zinc-400 ring-zinc-700/10 dark:ring-zinc-400/20',\n error: 'bg-red-50 dark:bg-red-500/10 text-red-700 dark:text-red-400 ring-red-700/10 dark:ring-red-400/20',\n uninstalled: 'bg-zinc-100 dark:bg-zinc-600/10 text-zinc-600 dark:text-zinc-500 ring-zinc-600/10 dark:ring-zinc-500/20'\n }\n\n const statusIcons = {\n active: '<div class=\"w-2 h-2 bg-lime-500 dark:bg-lime-400 rounded-full mr-2\"></div>',\n inactive: '<div class=\"w-2 h-2 bg-zinc-500 dark:bg-zinc-400 rounded-full mr-2\"></div>',\n error: '<div class=\"w-2 h-2 bg-red-500 dark:bg-red-400 rounded-full mr-2\"></div>',\n uninstalled: '<div class=\"w-2 h-2 bg-zinc-400 dark:bg-zinc-600 rounded-full mr-2\"></div>'\n }\n\n // Border colors based on status\n const borderColors = {\n active: 'ring-[3px] ring-lime-500 dark:ring-lime-400',\n inactive: 'ring-[3px] ring-pink-500 dark:ring-pink-400',\n error: 'ring-[3px] ring-red-500 dark:ring-red-400',\n uninstalled: 'ring-[3px] ring-zinc-400 dark:ring-zinc-600'\n }\n\n // Core system plugins that cannot be deactivated\n const criticalCorePlugins = ['core-auth', 'core-media']\n const canToggle = !criticalCorePlugins.includes(plugin.id)\n\n let actionButton = ''\n if (plugin.status === 'uninstalled') {\n actionButton = `<button onclick=\"installPlugin('${plugin.name}')\" class=\"bg-cyan-600 dark:bg-cyan-700 hover:bg-cyan-700 dark:hover:bg-cyan-600 text-white px-3 py-1.5 rounded-lg text-sm font-medium transition-colors\">Install</button>`\n } else if (plugin.status === 'active') {\n actionButton = `<button onclick=\"togglePlugin('${plugin.id}', 'deactivate')\" class=\"bg-red-600 dark:bg-red-700 hover:bg-red-700 dark:hover:bg-red-600 text-white px-3 py-1.5 rounded-lg text-sm font-medium transition-colors\">Deactivate</button>`\n } else {\n actionButton = `<button onclick=\"togglePlugin('${plugin.id}', 'activate')\" class=\"bg-lime-600 dark:bg-lime-700 hover:bg-lime-700 dark:hover:bg-lime-600 text-white px-3 py-1.5 rounded-lg text-sm font-medium transition-colors\">Activate</button>`\n }\n\n return `\n <div class=\"plugin-card rounded-xl bg-white dark:bg-zinc-900 shadow-sm ${borderColors[plugin.status]} p-6 hover:bg-zinc-50 dark:hover:bg-zinc-800/50 transition-all\" data-category=\"${plugin.category}\" data-status=\"${plugin.status}\" data-name=\"${plugin.displayName}\" data-description=\"${plugin.description}\">\n <div class=\"flex items-start justify-between mb-4\">\n <div class=\"flex items-center gap-3\">\n <div class=\"w-12 h-12 rounded-lg flex items-center justify-center ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 bg-zinc-50 dark:bg-zinc-800\">\n ${plugin.icon || getDefaultPluginIcon(plugin.category)}\n </div>\n <div>\n <h3 class=\"text-lg font-semibold text-zinc-950 dark:text-white\">${plugin.displayName}</h3>\n <p class=\"text-sm text-zinc-500 dark:text-zinc-400\">v${plugin.version} by ${plugin.author}</p>\n </div>\n </div>\n <div class=\"flex flex-col items-end gap-2\">\n <span class=\"status-badge inline-flex items-center rounded-md px-2.5 py-1 text-sm font-medium ring-1 ring-inset ${statusColors[plugin.status]}\">\n ${statusIcons[plugin.status]}${plugin.status.charAt(0).toUpperCase() + plugin.status.slice(1)}\n </span>\n ${plugin.isCore ? '<span class=\"inline-flex items-center rounded-md px-2.5 py-1 text-sm font-medium bg-cyan-50 dark:bg-cyan-500/10 text-cyan-700 dark:text-cyan-300 ring-1 ring-inset ring-cyan-700/10 dark:ring-cyan-400/20\">Core</span>' : ''}\n </div>\n </div>\n\n <p class=\"text-zinc-600 dark:text-zinc-300 text-sm mb-4 line-clamp-3\">${plugin.description}</p>\n\n <div class=\"flex items-center gap-4 mb-4 text-xs text-zinc-500 dark:text-zinc-400\">\n <span class=\"flex items-center gap-1\">\n <svg class=\"w-4 h-4\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M7 7h.01M7 3h5c.512 0 1.024.195 1.414.586l7 7a2 2 0 010 2.828l-7 7a2 2 0 01-2.828 0l-7-7A1.994 1.994 0 013 12V7a4 4 0 014-4z\"/>\n </svg>\n ${plugin.category}\n </span>\n\n ${plugin.downloadCount ? `\n <span class=\"flex items-center gap-1\">\n <svg class=\"w-4 h-4\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M7 16a4 4 0 01-.88-7.903A5 5 0 1115.9 6L16 6a5 5 0 011 9.9M15 13l-3-3m0 0l-3 3m3-3v12\"/>\n </svg>\n ${plugin.downloadCount.toLocaleString()}\n </span>\n ` : ''}\n\n ${plugin.rating ? `\n <span class=\"flex items-center gap-1\">\n <svg class=\"w-4 h-4 text-yellow-500 dark:text-yellow-400 fill-current\" viewBox=\"0 0 24 24\">\n <path d=\"M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z\"/>\n </svg>\n ${plugin.rating}\n </span>\n ` : ''}\n\n <span>${plugin.lastUpdated}</span>\n </div>\n\n ${plugin.dependencies && plugin.dependencies.length > 0 ? `\n <div class=\"mb-4\">\n <p class=\"text-xs text-zinc-500 dark:text-zinc-400 mb-2\">Dependencies:</p>\n <div class=\"flex flex-wrap gap-1\">\n ${plugin.dependencies.map(dep => `<span class=\"inline-block bg-zinc-100 dark:bg-zinc-800 text-zinc-700 dark:text-zinc-300 text-xs px-2 py-1 rounded\">${dep}</span>`).join('')}\n </div>\n </div>\n ` : ''}\n\n <div class=\"flex items-center justify-between\">\n <div class=\"flex gap-2\">\n ${plugin.status === 'uninstalled' ? actionButton : (canToggle ? actionButton : '')}\n ${plugin.status !== 'uninstalled' ? `\n <button onclick=\"openPluginSettings('${plugin.id}')\" class=\"bg-white dark:bg-zinc-800 hover:bg-zinc-50 dark:hover:bg-zinc-700 text-zinc-950 dark:text-white ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 px-3 py-1.5 rounded-lg text-sm font-medium transition-colors\">\n Settings\n </button>\n ` : ''}\n </div>\n\n <div class=\"flex items-center gap-2\">\n ${plugin.status !== 'uninstalled' ? `\n <button onclick=\"showPluginDetails('${plugin.id}')\" class=\"text-zinc-500 dark:text-zinc-400 hover:text-zinc-700 dark:hover:text-zinc-300 p-1.5 rounded-lg hover:bg-zinc-100 dark:hover:bg-zinc-800 transition-colors\" title=\"Plugin Details\">\n <svg class=\"w-4 h-4\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z\"/>\n </svg>\n </button>\n ` : ''}\n\n ${!plugin.isCore && plugin.status !== 'uninstalled' ? `\n <button onclick=\"uninstallPlugin('${plugin.id}')\" class=\"text-zinc-500 dark:text-zinc-400 hover:text-red-600 dark:hover:text-red-400 p-1.5 rounded-lg hover:bg-zinc-100 dark:hover:bg-zinc-800 transition-colors\" title=\"Uninstall Plugin\">\n <svg class=\"w-4 h-4\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16\"/>\n </svg>\n </button>\n ` : ''}\n </div>\n </div>\n </div>\n `\n}\n\nfunction getDefaultPluginIcon(category: string): string {\n const iconColor = 'text-zinc-600 dark:text-zinc-400'\n\n const icons: Record<string, string> = {\n 'content': `\n <svg class=\"w-6 h-6 ${iconColor}\" fill=\"none\" viewBox=\"0 0 24 24\" stroke-width=\"1.5\" stroke=\"currentColor\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M19.5 14.25v-2.625a3.375 3.375 0 0 0-3.375-3.375h-1.5A1.125 1.125 0 0 1 13.5 7.125v-1.5a3.375 3.375 0 0 0-3.375-3.375H8.25m0 12.75h7.5m-7.5 3H12M10.5 2.25H5.625c-.621 0-1.125.504-1.125 1.125v17.25c0 .621.504 1.125 1.125 1.125h12.75c.621 0 1.125-.504 1.125-1.125V11.25a9 9 0 0 0-9-9Z\" />\n </svg>\n `,\n 'media': `\n <svg class=\"w-6 h-6 ${iconColor}\" fill=\"none\" viewBox=\"0 0 24 24\" stroke-width=\"1.5\" stroke=\"currentColor\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"m2.25 15.75 5.159-5.159a2.25 2.25 0 0 1 3.182 0l5.159 5.159m-1.5-1.5 1.409-1.409a2.25 2.25 0 0 1 3.182 0l2.909 2.909m-18 3.75h16.5a1.5 1.5 0 0 0 1.5-1.5V6a1.5 1.5 0 0 0-1.5-1.5H3.75A1.5 1.5 0 0 0 2.25 6v12a1.5 1.5 0 0 0 1.5 1.5Zm10.5-11.25h.008v.008h-.008V8.25Zm.375 0a.375.375 0 1 1-.75 0 .375.375 0 0 1 .75 0Z\" />\n </svg>\n `,\n 'seo': `\n <svg class=\"w-6 h-6 ${iconColor}\" fill=\"none\" viewBox=\"0 0 24 24\" stroke-width=\"1.5\" stroke=\"currentColor\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"m21 21-5.197-5.197m0 0A7.5 7.5 0 1 0 5.196 5.196a7.5 7.5 0 0 0 10.607 10.607Z\" />\n </svg>\n `,\n 'analytics': `\n <svg class=\"w-6 h-6 ${iconColor}\" fill=\"none\" viewBox=\"0 0 24 24\" stroke-width=\"1.5\" stroke=\"currentColor\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M3 13.125C3 12.504 3.504 12 4.125 12h2.25c.621 0 1.125.504 1.125 1.125v6.75C7.5 20.496 6.996 21 6.375 21h-2.25A1.125 1.125 0 0 1 3 19.875v-6.75ZM9.75 8.625c0-.621.504-1.125 1.125-1.125h2.25c.621 0 1.125.504 1.125 1.125v11.25c0 .621-.504 1.125-1.125 1.125h-2.25a1.125 1.125 0 0 1-1.125-1.125V8.625ZM16.5 4.125c0-.621.504-1.125 1.125-1.125h2.25C20.496 3 21 3.504 21 4.125v15.75c0 .621-.504 1.125-1.125 1.125h-2.25a1.125 1.125 0 0 1-1.125-1.125V4.125Z\" />\n </svg>\n `,\n 'ecommerce': `\n <svg class=\"w-6 h-6 ${iconColor}\" fill=\"none\" viewBox=\"0 0 24 24\" stroke-width=\"1.5\" stroke=\"currentColor\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M2.25 3h1.386c.51 0 .955.343 1.087.835l.383 1.437M7.5 14.25a3 3 0 0 0-3 3h15.75m-12.75-3h11.218c1.121-2.3 2.1-4.684 2.924-7.138a60.114 60.114 0 0 0-16.536-1.84M7.5 14.25 5.106 5.272M6 20.25a.75.75 0 1 1-1.5 0 .75.75 0 0 1 1.5 0Zm12.75 0a.75.75 0 1 1-1.5 0 .75.75 0 0 1 1.5 0Z\" />\n </svg>\n `,\n 'email': `\n <svg class=\"w-6 h-6 ${iconColor}\" fill=\"none\" viewBox=\"0 0 24 24\" stroke-width=\"1.5\" stroke=\"currentColor\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M21.75 6.75v10.5a2.25 2.25 0 0 1-2.25 2.25h-15a2.25 2.25 0 0 1-2.25-2.25V6.75m19.5 0A2.25 2.25 0 0 0 19.5 4.5h-15a2.25 2.25 0 0 0-2.25 2.25m19.5 0v.243a2.25 2.25 0 0 1-1.07 1.916l-7.5 4.615a2.25 2.25 0 0 1-2.36 0L3.32 8.91a2.25 2.25 0 0 1-1.07-1.916V6.75\" />\n </svg>\n `,\n 'workflow': `\n <svg class=\"w-6 h-6 ${iconColor}\" fill=\"none\" viewBox=\"0 0 24 24\" stroke-width=\"1.5\" stroke=\"currentColor\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M16.023 9.348h4.992v-.001M2.985 19.644v-4.992m0 0h4.992m-4.993 0 3.181 3.183a8.25 8.25 0 0 0 13.803-3.7M4.031 9.865a8.25 8.25 0 0 1 13.803-3.7l3.181 3.182m0-4.991v4.99\" />\n </svg>\n `,\n 'security': `\n <svg class=\"w-6 h-6 ${iconColor}\" fill=\"none\" viewBox=\"0 0 24 24\" stroke-width=\"1.5\" stroke=\"currentColor\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M16.5 10.5V6.75a4.5 4.5 0 1 0-9 0v3.75m-.75 11.25h10.5a2.25 2.25 0 0 0 2.25-2.25v-6.75a2.25 2.25 0 0 0-2.25-2.25H6.75a2.25 2.25 0 0 0-2.25 2.25v6.75a2.25 2.25 0 0 0 2.25 2.25Z\" />\n </svg>\n `,\n 'social': `\n <svg class=\"w-6 h-6 ${iconColor}\" fill=\"none\" viewBox=\"0 0 24 24\" stroke-width=\"1.5\" stroke=\"currentColor\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M18 18.72a9.094 9.094 0 0 0 3.741-.479 3 3 0 0 0-4.682-2.72m.94 3.198.001.031c0 .225-.012.447-.037.666A11.944 11.944 0 0 1 12 21c-2.17 0-4.207-.576-5.963-1.584A6.062 6.062 0 0 1 6 18.719m12 0a5.971 5.971 0 0 0-.941-3.197m0 0A5.995 5.995 0 0 0 12 12.75a5.995 5.995 0 0 0-5.058 2.772m0 0a3 3 0 0 0-4.681 2.72 8.986 8.986 0 0 0 3.74.477m.94-3.197a5.971 5.971 0 0 0-.94 3.197M15 6.75a3 3 0 1 1-6 0 3 3 0 0 1 6 0Zm6 3a2.25 2.25 0 1 1-4.5 0 2.25 2.25 0 0 1 4.5 0Zm-13.5 0a2.25 2.25 0 1 1-4.5 0 2.25 2.25 0 0 1 4.5 0Z\" />\n </svg>\n `,\n 'utility': `\n <svg class=\"w-6 h-6 ${iconColor}\" fill=\"none\" viewBox=\"0 0 24 24\" stroke-width=\"1.5\" stroke=\"currentColor\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9.594 3.94c.09-.542.56-.94 1.11-.94h2.593c.55 0 1.02.398 1.11.94l.213 1.281c.063.374.313.686.645.87.074.04.147.083.22.127.325.196.72.257 1.075.124l1.217-.456a1.125 1.125 0 0 1 1.37.49l1.296 2.247a1.125 1.125 0 0 1-.26 1.431l-1.003.827c-.293.241-.438.613-.43.992a7.723 7.723 0 0 1 0 .255c-.008.378.137.75.43.991l1.004.827c.424.35.534.955.26 1.43l-1.298 2.247a1.125 1.125 0 0 1-1.369.491l-1.217-.456c-.355-.133-.75-.072-1.076.124a6.47 6.47 0 0 1-.22.128c-.331.183-.581.495-.644.869l-.213 1.281c-.09.543-.56.94-1.11.94h-2.594c-.55 0-1.019-.398-1.11-.94l-.213-1.281c-.062-.374-.312-.686-.644-.87a6.52 6.52 0 0 1-.22-.127c-.325-.196-.72-.257-1.076-.124l-1.217.456a1.125 1.125 0 0 1-1.369-.49l-1.297-2.247a1.125 1.125 0 0 1 .26-1.431l1.004-.827c.292-.24.437-.613.43-.991a6.932 6.932 0 0 1 0-.255c.007-.38-.138-.751-.43-.992l-1.004-.827a1.125 1.125 0 0 1-.26-1.43l1.297-2.247a1.125 1.125 0 0 1 1.37-.491l1.216.456c.356.133.751.072 1.076-.124.072-.044.146-.086.22-.128.332-.183.582-.495.644-.869l.214-1.28Z\" />\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M15 12a3 3 0 1 1-6 0 3 3 0 0 1 6 0Z\" />\n </svg>\n `,\n }\n\n const iconKey = category.toLowerCase() as keyof typeof icons\n return icons[iconKey] || icons['utility'] || ''\n}\n\n// Mock data generator\nexport function generateMockPlugins(): Plugin[] {\n return [\n {\n id: '1',\n name: 'seo-optimizer',\n displayName: 'SEO Optimizer',\n description: 'Advanced SEO optimization tools including meta tag management, sitemap generation, and analytics integration. Boost your search engine rankings with automated optimizations.',\n version: '2.1.4',\n author: 'SonicJS Team',\n status: 'active',\n category: 'seo',\n icon: `<svg class=\"w-6 h-6\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\"><path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M13 10V3L4 14h7v7l9-11h-7z\"/></svg>`,\n downloadCount: 15420,\n rating: 4.8,\n lastUpdated: '2 days ago',\n dependencies: ['analytics-plugin'],\n permissions: ['read:content', 'write:meta'],\n isCore: true\n },\n {\n id: '2',\n name: 'image-optimizer',\n displayName: 'Image Optimizer',\n description: 'Automatically compress and optimize images on upload. Supports WebP conversion, lazy loading, and responsive image generation for better performance.',\n version: '1.5.2',\n author: 'MediaPro',\n status: 'active',\n category: 'media',\n icon: `<svg class=\"w-6 h-6\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\"><path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z\"/></svg>`,\n downloadCount: 8930,\n rating: 4.6,\n lastUpdated: '1 week ago',\n dependencies: [],\n permissions: ['write:media', 'read:settings']\n },\n {\n id: '3',\n name: 'backup-manager',\n displayName: 'Backup Manager',\n description: 'Automated backup solution for content and media files. Schedule regular backups to cloud storage with encryption and restore capabilities.',\n version: '3.0.1',\n author: 'BackupCorp',\n status: 'inactive',\n category: 'utilities',\n icon: `<svg class=\"w-6 h-6\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\"><path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M8 7H5a2 2 0 00-2 2v9a2 2 0 002 2h14a2 2 0 002-2V9a2 2 0 00-2-2h-3m-1 4l-3 3m0 0l-3-3m3 3V4\"/></svg>`,\n downloadCount: 12450,\n rating: 4.9,\n lastUpdated: '3 days ago',\n dependencies: ['cloud-storage'],\n permissions: ['read:all', 'write:backups']\n },\n {\n id: '4',\n name: 'security-scanner',\n displayName: 'Security Scanner',\n description: 'Real-time security monitoring and vulnerability scanning. Detects malware, suspicious activities, and provides security recommendations.',\n version: '1.2.8',\n author: 'SecureWeb',\n status: 'error',\n category: 'security',\n icon: `<svg class=\"w-6 h-6\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\"><path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M9 12l2 2 4-4m5.618-4.016A11.955 11.955 0 0112 2.944a11.955 11.955 0 01-8.618 3.04A12.02 12.02 0 003 9c0 5.591 3.824 10.29 9 11.622 5.176-1.332 9-6.03 9-11.622 0-1.042-.133-2.052-.382-3.016z\"/></svg>`,\n downloadCount: 5680,\n rating: 4.3,\n lastUpdated: '5 days ago',\n dependencies: ['security-core'],\n permissions: ['read:logs', 'read:files', 'write:security']\n },\n {\n id: '5',\n name: 'social-share',\n displayName: 'Social Share',\n description: 'Easy social media sharing buttons and Open Graph meta tag generation. Supports all major social platforms with customizable styling.',\n version: '2.3.0',\n author: 'SocialPlus',\n status: 'active',\n category: 'content',\n icon: `<svg class=\"w-6 h-6\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\"><path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M8.684 13.342C8.886 12.938 9 12.482 9 12c0-.482-.114-.938-.316-1.342m0 2.684a3 3 0 110-2.684m0 2.684l6.632 3.316m-6.632-6l6.632-3.316m0 0a3 3 0 105.367-2.684 3 3 0 00-5.367 2.684zm0 9.316a3 3 0 105.368 2.684 3 3 0 00-5.368-2.684z\"/></svg>`,\n downloadCount: 22100,\n rating: 4.7,\n lastUpdated: '4 days ago',\n dependencies: [],\n permissions: ['read:content', 'write:meta']\n },\n {\n id: '6',\n name: 'analytics-pro',\n displayName: 'Analytics Pro',\n description: 'Advanced analytics dashboard with custom tracking events, conversion funnels, and detailed visitor insights. GDPR compliant with privacy controls.',\n version: '4.1.2',\n author: 'AnalyticsPro Inc',\n status: 'active',\n category: 'seo',\n icon: `<svg class=\"w-6 h-6\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\"><path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z\"/></svg>`,\n downloadCount: 18750,\n rating: 4.9,\n lastUpdated: '1 day ago',\n dependencies: ['gdpr-compliance'],\n permissions: ['read:analytics', 'write:tracking', 'read:users']\n },\n {\n id: '7',\n name: 'form-builder',\n displayName: 'Advanced Form Builder',\n description: 'Drag-and-drop form builder with conditional logic, file uploads, payment integration, and email notifications. Perfect for contact forms and surveys.',\n version: '1.8.5',\n author: 'FormWorks',\n status: 'inactive',\n category: 'content',\n icon: `<svg class=\"w-6 h-6\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\"><path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z\"/></svg>`,\n downloadCount: 9870,\n rating: 4.4,\n lastUpdated: '1 week ago',\n dependencies: ['email-service'],\n permissions: ['write:forms', 'read:submissions', 'send:emails']\n },\n {\n id: '8',\n name: 'cache-optimizer',\n displayName: 'Cache Optimizer',\n description: 'Intelligent caching system with Redis support, CDN integration, and automatic cache invalidation. Dramatically improves site performance.',\n version: '2.7.3',\n author: 'SpeedBoost',\n status: 'active',\n category: 'utilities',\n icon: `<svg class=\"w-6 h-6\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\"><path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M13 10V3L4 14h7v7l9-11h-7z\"/></svg>`,\n downloadCount: 13240,\n rating: 4.8,\n lastUpdated: '6 days ago',\n dependencies: ['redis-connector'],\n permissions: ['read:cache', 'write:cache', 'manage:cdn'],\n isCore: true\n },\n {\n id: '9',\n name: 'multilingual',\n displayName: 'Multilingual Support',\n description: 'Complete internationalization solution with automatic translation, language detection, and localized content management for global websites.',\n version: '3.2.1',\n author: 'GlobalWeb',\n status: 'active',\n category: 'content',\n icon: `<svg class=\"w-6 h-6\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\"><path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M3 5h12M9 3v2m1.048 9.5A18.022 18.022 0 016.412 9m6.088 9h7M11 21l5-10 5 10M12.751 5C11.783 10.77 8.07 15.61 3 18.129\"/></svg>`,\n downloadCount: 7650,\n rating: 4.5,\n lastUpdated: '2 weeks ago',\n dependencies: ['translation-api'],\n permissions: ['read:content', 'write:translations', 'manage:languages']\n }\n ]\n}","import type { AuthSettings } from '../../services/auth-validation'\n\nexport function renderAuthSettingsForm(settings: AuthSettings): string {\n const fields = settings.requiredFields\n const validation = settings.validation\n const registration = settings.registration\n\n return `\n <div class=\"space-y-8\">\n <!-- Required Fields Section -->\n <div class=\"backdrop-blur-md bg-black/20 rounded-xl border border-white/10 shadow-xl p-6\">\n <h3 class=\"text-lg font-semibold text-white mb-4\">Registration Fields</h3>\n <p class=\"text-sm text-gray-400 mb-6\">Configure which fields are required during user registration and their minimum lengths.</p>\n\n <div class=\"space-y-6\">\n ${Object.entries(fields).map(([fieldName, config]: [string, any]) => `\n <div class=\"border-b border-white/10 pb-6 last:border-b-0 last:pb-0\">\n <div class=\"flex items-start justify-between mb-4\">\n <div>\n <h4 class=\"text-sm font-medium text-white\">${config.label}</h4>\n <p class=\"text-xs text-gray-400 mt-1\">Field type: ${config.type}</p>\n </div>\n <label class=\"relative inline-flex items-center cursor-pointer\">\n <input\n type=\"checkbox\"\n name=\"requiredFields_${fieldName}_required\"\n ${config.required ? 'checked' : ''}\n class=\"sr-only peer\"\n >\n <div class=\"w-11 h-6 bg-gray-600 peer-focus:outline-none peer-focus:ring-4 peer-focus:ring-blue-800 rounded-full peer peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:rounded-full after:h-5 after:w-5 after:transition-all peer-checked:bg-blue-600\"></div>\n <span class=\"ml-3 text-sm font-medium text-gray-300\">Required</span>\n </label>\n </div>\n\n <div class=\"grid grid-cols-2 gap-4\">\n <div>\n <label class=\"block text-xs font-medium text-gray-400 mb-2\">Minimum Length</label>\n <input\n type=\"number\"\n name=\"requiredFields_${fieldName}_minLength\"\n value=\"${config.minLength}\"\n min=\"0\"\n max=\"100\"\n class=\"backdrop-blur-sm bg-white/10 border border-white/20 rounded-lg px-3 py-2 text-white placeholder-gray-300 focus:border-blue-400 focus:outline-none transition-colors w-full\"\n >\n </div>\n <div>\n <label class=\"block text-xs font-medium text-gray-400 mb-2\">Field Label</label>\n <input\n type=\"text\"\n name=\"requiredFields_${fieldName}_label\"\n value=\"${config.label}\"\n class=\"backdrop-blur-sm bg-white/10 border border-white/20 rounded-lg px-3 py-2 text-white placeholder-gray-300 focus:border-blue-400 focus:outline-none transition-colors w-full\"\n >\n </div>\n </div>\n </div>\n `).join('')}\n </div>\n </div>\n\n <!-- Password Requirements Section -->\n <div class=\"backdrop-blur-md bg-black/20 rounded-xl border border-white/10 shadow-xl p-6\">\n <h3 class=\"text-lg font-semibold text-white mb-4\">Password Requirements</h3>\n <p class=\"text-sm text-gray-400 mb-6\">Additional password complexity requirements.</p>\n\n <div class=\"space-y-4\">\n <div class=\"flex items-center justify-between\">\n <div>\n <label class=\"text-sm font-medium text-gray-300\">Require Uppercase Letter</label>\n <p class=\"text-xs text-gray-400\">Password must contain at least one uppercase letter (A-Z)</p>\n </div>\n <label class=\"relative inline-flex items-center cursor-pointer\">\n <input\n type=\"checkbox\"\n name=\"validation_passwordRequirements_requireUppercase\"\n ${validation.passwordRequirements.requireUppercase ? 'checked' : ''}\n class=\"sr-only peer\"\n >\n <div class=\"w-11 h-6 bg-gray-600 peer-focus:outline-none peer-focus:ring-4 peer-focus:ring-blue-800 rounded-full peer peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:rounded-full after:h-5 after:w-5 after:transition-all peer-checked:bg-blue-600\"></div>\n </label>\n </div>\n\n <div class=\"flex items-center justify-between\">\n <div>\n <label class=\"text-sm font-medium text-gray-300\">Require Lowercase Letter</label>\n <p class=\"text-xs text-gray-400\">Password must contain at least one lowercase letter (a-z)</p>\n </div>\n <label class=\"relative inline-flex items-center cursor-pointer\">\n <input\n type=\"checkbox\"\n name=\"validation_passwordRequirements_requireLowercase\"\n ${validation.passwordRequirements.requireLowercase ? 'checked' : ''}\n class=\"sr-only peer\"\n >\n <div class=\"w-11 h-6 bg-gray-600 peer-focus:outline-none peer-focus:ring-4 peer-focus:ring-blue-800 rounded-full peer peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:rounded-full after:h-5 after:w-5 after:transition-all peer-checked:bg-blue-600\"></div>\n </label>\n </div>\n\n <div class=\"flex items-center justify-between\">\n <div>\n <label class=\"text-sm font-medium text-gray-300\">Require Numbers</label>\n <p class=\"text-xs text-gray-400\">Password must contain at least one number (0-9)</p>\n </div>\n <label class=\"relative inline-flex items-center cursor-pointer\">\n <input\n type=\"checkbox\"\n name=\"validation_passwordRequirements_requireNumbers\"\n ${validation.passwordRequirements.requireNumbers ? 'checked' : ''}\n class=\"sr-only peer\"\n >\n <div class=\"w-11 h-6 bg-gray-600 peer-focus:outline-none peer-focus:ring-4 peer-focus:ring-blue-800 rounded-full peer peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:rounded-full after:h-5 after:w-5 after:transition-all peer-checked:bg-blue-600\"></div>\n </label>\n </div>\n\n <div class=\"flex items-center justify-between\">\n <div>\n <label class=\"text-sm font-medium text-gray-300\">Require Special Characters</label>\n <p class=\"text-xs text-gray-400\">Password must contain at least one special character (!@#$%^&*)</p>\n </div>\n <label class=\"relative inline-flex items-center cursor-pointer\">\n <input\n type=\"checkbox\"\n name=\"validation_passwordRequirements_requireSpecialChars\"\n ${validation.passwordRequirements.requireSpecialChars ? 'checked' : ''}\n class=\"sr-only peer\"\n >\n <div class=\"w-11 h-6 bg-gray-600 peer-focus:outline-none peer-focus:ring-4 peer-focus:ring-blue-800 rounded-full peer peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:rounded-full after:h-5 after:w-5 after:transition-all peer-checked:bg-blue-600\"></div>\n </label>\n </div>\n </div>\n </div>\n\n <!-- Registration Settings Section -->\n <div class=\"backdrop-blur-md bg-black/20 rounded-xl border border-white/10 shadow-xl p-6\">\n <h3 class=\"text-lg font-semibold text-white mb-4\">Registration Settings</h3>\n <p class=\"text-sm text-gray-400 mb-6\">General registration behavior.</p>\n\n <div class=\"space-y-4\">\n <div class=\"flex items-center justify-between\">\n <div>\n <label class=\"text-sm font-medium text-gray-300\">Allow User Registration</label>\n <p class=\"text-xs text-gray-400\">Enable or disable public user registration</p>\n </div>\n <label class=\"relative inline-flex items-center cursor-pointer\">\n <input\n type=\"checkbox\"\n name=\"registration_enabled\"\n ${registration.enabled ? 'checked' : ''}\n class=\"sr-only peer\"\n >\n <div class=\"w-11 h-6 bg-gray-600 peer-focus:outline-none peer-focus:ring-4 peer-focus:ring-blue-800 rounded-full peer peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:rounded-full after:h-5 after:w-5 after:transition-all peer-checked:bg-blue-600\"></div>\n </label>\n </div>\n\n <div class=\"flex items-center justify-between\">\n <div>\n <label class=\"text-sm font-medium text-gray-300\">Require Email Verification</label>\n <p class=\"text-xs text-gray-400\">Users must verify their email before accessing the system</p>\n </div>\n <label class=\"relative inline-flex items-center cursor-pointer\">\n <input\n type=\"checkbox\"\n name=\"registration_requireEmailVerification\"\n ${registration.requireEmailVerification ? 'checked' : ''}\n class=\"sr-only peer\"\n >\n <div class=\"w-11 h-6 bg-gray-600 peer-focus:outline-none peer-focus:ring-4 peer-focus:ring-blue-800 rounded-full peer peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:rounded-full after:h-5 after:w-5 after:transition-all peer-checked:bg-blue-600\"></div>\n </label>\n </div>\n\n <div>\n <label class=\"block text-sm font-medium text-gray-300 mb-2\">Default User Role</label>\n <select\n name=\"registration_defaultRole\"\n class=\"backdrop-blur-sm bg-white/10 border border-white/20 rounded-lg px-3 py-2 text-white focus:border-blue-400 focus:outline-none transition-colors w-full\"\n >\n <option value=\"viewer\" ${registration.defaultRole === 'viewer' ? 'selected' : ''}>Viewer</option>\n <option value=\"editor\" ${registration.defaultRole === 'editor' ? 'selected' : ''}>Editor</option>\n <option value=\"admin\" ${registration.defaultRole === 'admin' ? 'selected' : ''}>Admin</option>\n </select>\n <p class=\"text-xs text-gray-400 mt-1\">Role assigned to new users upon registration</p>\n </div>\n </div>\n </div>\n\n <!-- Validation Settings Section -->\n <div class=\"backdrop-blur-md bg-black/20 rounded-xl border border-white/10 shadow-xl p-6\">\n <h3 class=\"text-lg font-semibold text-white mb-4\">Validation Settings</h3>\n <p class=\"text-sm text-gray-400 mb-6\">Additional validation rules.</p>\n\n <div class=\"space-y-4\">\n <div class=\"flex items-center justify-between\">\n <div>\n <label class=\"text-sm font-medium text-gray-300\">Enforce Email Format</label>\n <p class=\"text-xs text-gray-400\">Validate that email addresses are in correct format</p>\n </div>\n <label class=\"relative inline-flex items-center cursor-pointer\">\n <input\n type=\"checkbox\"\n name=\"validation_emailFormat\"\n ${validation.emailFormat ? 'checked' : ''}\n class=\"sr-only peer\"\n >\n <div class=\"w-11 h-6 bg-gray-600 peer-focus:outline-none peer-focus:ring-4 peer-focus:ring-blue-800 rounded-full peer peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:rounded-full after:h-5 after:w-5 after:transition-all peer-checked:bg-blue-600\"></div>\n </label>\n </div>\n\n <div class=\"flex items-center justify-between\">\n <div>\n <label class=\"text-sm font-medium text-gray-300\">Prevent Duplicate Usernames</label>\n <p class=\"text-xs text-gray-400\">Ensure usernames are unique across all users</p>\n </div>\n <label class=\"relative inline-flex items-center cursor-pointer\">\n <input\n type=\"checkbox\"\n name=\"validation_allowDuplicateUsernames\"\n ${!validation.allowDuplicateUsernames ? 'checked' : ''}\n class=\"sr-only peer\"\n >\n <div class=\"w-11 h-6 bg-gray-600 peer-focus:outline-none peer-focus:ring-4 peer-focus:ring-blue-800 rounded-full peer peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:rounded-full after:h-5 after:w-5 after:transition-all peer-checked:bg-blue-600\"></div>\n </label>\n </div>\n </div>\n </div>\n </div>\n `\n}\n","import { renderAdminLayout, AdminLayoutData } from '../layouts/admin-layout-v2.template'\nimport { renderAuthSettingsForm } from '../components/auth-settings-form.template'\nimport type { AuthSettings } from '../../services/auth-validation'\n\nexport interface PluginSettings {\n [key: string]: any\n}\n\nexport interface PluginActivity {\n id: string\n action: string\n message: string\n timestamp: number\n user?: string\n}\n\nexport interface PluginSettingsPageData {\n plugin: {\n id: string\n name: string\n displayName: string\n description: string\n version: string\n author: string\n status: 'active' | 'inactive' | 'error'\n category: string\n icon: string\n downloadCount?: number\n rating?: number\n lastUpdated: string\n dependencies?: string[]\n permissions?: string[]\n isCore?: boolean\n settings?: PluginSettings\n }\n activity?: PluginActivity[]\n user?: {\n name: string\n email: string\n role: string\n }\n}\n\nexport function renderPluginSettingsPage(data: PluginSettingsPageData): string {\n const { plugin, activity = [], user } = data\n \n const pageContent = `\n <div class=\"w-full px-4 sm:px-6 lg:px-8 py-6\">\n <!-- Header with Back Button -->\n <div class=\"flex flex-col sm:flex-row sm:items-center sm:justify-between mb-6\">\n <div>\n <h1 class=\"text-2xl/8 font-semibold text-zinc-950 dark:text-white sm:text-xl/8\">Plugin Settings</h1>\n <p class=\"mt-2 text-sm/6 text-zinc-500 dark:text-zinc-400\">\n ${plugin.description}\n </p>\n </div>\n <div class=\"mt-4 sm:mt-0 sm:ml-16 sm:flex-none\">\n <a href=\"/admin/plugins\" class=\"inline-flex items-center justify-center rounded-lg bg-white dark:bg-zinc-800 px-3.5 py-2.5 text-sm font-semibold text-zinc-950 dark:text-white ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 hover:bg-zinc-50 dark:hover:bg-zinc-700 transition-colors shadow-sm\">\n <svg class=\"-ml-0.5 mr-1.5 h-5 w-5\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M10 19l-7-7m0 0l7-7m-7 7h18\"/>\n </svg>\n Back to Plugins\n </a>\n </div>\n </div>\n\n <!-- Plugin Header -->\n <div class=\"backdrop-blur-md bg-black/20 rounded-xl border border-white/10 shadow-xl p-6 mb-6\">\n <div class=\"flex items-start justify-between\">\n <div class=\"flex items-center gap-4\">\n <div class=\"w-16 h-16 bg-gradient-to-br from-blue-500 to-purple-600 rounded-xl flex items-center justify-center text-white text-2xl font-bold\">\n ${plugin.icon || plugin.displayName.charAt(0).toUpperCase()}\n </div>\n <div>\n <h2 class=\"text-2xl font-semibold text-white mb-1\">${plugin.displayName}</h2>\n <div class=\"flex items-center gap-4 text-sm text-gray-400 mt-2\">\n <span>v${plugin.version}</span>\n <span>by ${plugin.author}</span>\n <span>${plugin.category}</span>\n ${plugin.downloadCount ? `<span>${plugin.downloadCount.toLocaleString()} downloads</span>` : ''}\n ${plugin.rating ? `<span>★ ${plugin.rating}</span>` : ''}\n </div>\n </div>\n </div>\n\n <div class=\"flex items-center gap-3\">\n ${renderStatusBadge(plugin.status)}\n ${renderToggleButton(plugin)}\n </div>\n </div>\n </div>\n\n <!-- Tabs -->\n <div class=\"mb-6\">\n <nav class=\"flex space-x-8\" aria-label=\"Tabs\">\n <button onclick=\"showTab('settings')\" id=\"settings-tab\" class=\"tab-button active border-b-2 border-blue-400 py-2 px-1 text-sm font-medium text-blue-400\">\n Settings\n </button>\n <button onclick=\"showTab('activity')\" id=\"activity-tab\" class=\"tab-button border-b-2 border-transparent py-2 px-1 text-sm font-medium text-gray-400 hover:text-gray-300\">\n Activity Log\n </button>\n <button onclick=\"showTab('info')\" id=\"info-tab\" class=\"tab-button border-b-2 border-transparent py-2 px-1 text-sm font-medium text-gray-400 hover:text-gray-300\">\n Information\n </button>\n </nav>\n </div>\n\n <!-- Tab Content -->\n <div id=\"tab-content\">\n <!-- Settings Tab -->\n <div id=\"settings-content\" class=\"tab-content\">\n ${renderSettingsTab(plugin)}\n </div>\n\n <!-- Activity Tab -->\n <div id=\"activity-content\" class=\"tab-content hidden\">\n ${renderActivityTab(activity)}\n </div>\n\n <!-- Information Tab -->\n <div id=\"info-content\" class=\"tab-content hidden\">\n ${renderInformationTab(plugin)}\n </div>\n </div>\n </div>\n\n <script>\n function showTab(tabName) {\n // Hide all tab contents\n document.querySelectorAll('.tab-content').forEach(content => {\n content.classList.add('hidden');\n });\n \n // Remove active class from all tabs\n document.querySelectorAll('.tab-button').forEach(tab => {\n tab.classList.remove('active', 'border-blue-400', 'text-blue-400');\n tab.classList.add('border-transparent', 'text-gray-400');\n });\n \n // Show selected tab content\n document.getElementById(tabName + '-content').classList.remove('hidden');\n \n // Add active class to selected tab\n const activeTab = document.getElementById(tabName + '-tab');\n activeTab.classList.add('active', 'border-blue-400', 'text-blue-400');\n activeTab.classList.remove('border-transparent', 'text-gray-400');\n }\n\n async function togglePlugin(pluginId, action) {\n const button = event.target;\n const originalText = button.textContent;\n button.disabled = true;\n button.textContent = action === 'activate' ? 'Activating...' : 'Deactivating...';\n \n try {\n const response = await fetch(\\`/admin/plugins/\\${pluginId}/\\${action}\\`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json'\n }\n });\n \n const result = await response.json();\n \n if (result.success) {\n showNotification(\\`Plugin \\${action}d successfully\\`, 'success');\n setTimeout(() => location.reload(), 1000);\n } else {\n throw new Error(result.error || \\`Failed to \\${action} plugin\\`);\n }\n } catch (error) {\n showNotification(error.message, 'error');\n button.textContent = originalText;\n button.disabled = false;\n }\n }\n\n async function saveSettings() {\n const form = document.getElementById('settings-form');\n const formData = new FormData(form);\n const isAuthPlugin = '${plugin.id}' === 'core-auth';\n let settings = {};\n\n if (isAuthPlugin) {\n // Handle nested auth settings structure\n settings = {\n requiredFields: {},\n validation: {\n passwordRequirements: {}\n },\n registration: {}\n };\n\n for (let [key, value] of formData.entries()) {\n const input = form.querySelector(\\`[name=\"\\${key}\"]\\`);\n const fieldValue = input.type === 'checkbox' ? input.checked :\n input.type === 'number' ? parseInt(value) || 0 : value;\n\n // Parse nested field names like \"requiredFields_email_required\"\n if (key.startsWith('requiredFields_')) {\n const parts = key.replace('requiredFields_', '').split('_');\n const fieldName = parts[0];\n const propName = parts[1];\n\n if (!settings.requiredFields[fieldName]) {\n settings.requiredFields[fieldName] = { type: 'text', label: '' };\n }\n settings.requiredFields[fieldName][propName] = fieldValue;\n } else if (key.startsWith('validation_passwordRequirements_')) {\n const propName = key.replace('validation_passwordRequirements_', '');\n settings.validation.passwordRequirements[propName] = fieldValue;\n } else if (key.startsWith('validation_')) {\n const propName = key.replace('validation_', '');\n // Invert the allowDuplicateUsernames logic\n if (propName === 'allowDuplicateUsernames') {\n settings.validation[propName] = !fieldValue;\n } else {\n settings.validation[propName] = fieldValue;\n }\n } else if (key.startsWith('registration_')) {\n const propName = key.replace('registration_', '');\n settings.registration[propName] = fieldValue;\n }\n }\n } else {\n // Handle regular plugin settings\n for (let [key, value] of formData.entries()) {\n if (key.startsWith('setting_')) {\n const settingKey = key.replace('setting_', '');\n\n const input = form.querySelector(\\`[name=\"\\${key}\"]\\`);\n if (input.type === 'checkbox') {\n settings[settingKey] = input.checked;\n } else if (input.type === 'number') {\n settings[settingKey] = parseInt(value) || 0;\n } else {\n settings[settingKey] = value;\n }\n }\n }\n }\n\n const saveButton = document.getElementById('save-button');\n saveButton.disabled = true;\n saveButton.textContent = 'Saving...';\n\n try {\n const response = await fetch(\\`/admin/plugins/${plugin.id}/settings\\`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json'\n },\n body: JSON.stringify(settings)\n });\n\n const result = await response.json();\n\n if (result.success) {\n showNotification('Settings saved successfully', 'success');\n // Reload page after 1 second to show updated settings\n setTimeout(() => location.reload(), 1000);\n } else {\n throw new Error(result.error || 'Failed to save settings');\n }\n } catch (error) {\n showNotification(error.message, 'error');\n } finally {\n saveButton.disabled = false;\n saveButton.textContent = 'Save Settings';\n }\n }\n\n function showNotification(message, type) {\n const notification = document.createElement('div');\n const bgColor = type === 'success' ? 'bg-green-600' : type === 'error' ? 'bg-red-600' : 'bg-blue-600';\n notification.className = \\`fixed top-4 right-4 px-4 py-2 rounded-lg text-white z-50 \\${bgColor}\\`;\n notification.textContent = message;\n document.body.appendChild(notification);\n \n setTimeout(() => {\n notification.remove();\n }, 3000);\n }\n </script>\n `\n\n const layoutData: AdminLayoutData = {\n title: `${plugin.displayName} Settings`,\n pageTitle: `${plugin.displayName} Settings`,\n currentPath: `/admin/plugins/${plugin.id}`,\n user,\n content: pageContent\n }\n\n return renderAdminLayout(layoutData)\n}\n\nfunction renderStatusBadge(status: string): string {\n const statusColors: Record<string, string> = {\n active: 'bg-green-900/50 text-green-300 border-green-600/30',\n inactive: 'bg-gray-800/50 text-gray-400 border-gray-600/30',\n error: 'bg-red-900/50 text-red-300 border-red-600/30'\n }\n\n const statusIcons: Record<string, string> = {\n active: '<div class=\"w-2 h-2 bg-green-400 rounded-full mr-2\"></div>',\n inactive: '<div class=\"w-2 h-2 bg-gray-500 rounded-full mr-2\"></div>',\n error: '<div class=\"w-2 h-2 bg-red-400 rounded-full mr-2\"></div>'\n }\n\n return `\n <span class=\"inline-flex items-center px-3 py-1 rounded-full text-sm font-medium ${statusColors[status] || statusColors.inactive} border\">\n ${statusIcons[status] || statusIcons.inactive}${status.charAt(0).toUpperCase() + status.slice(1)}\n </span>\n `\n}\n\nfunction renderToggleButton(plugin: any): string {\n if (plugin.isCore) {\n return '<span class=\"text-sm text-gray-400\">Core Plugin</span>'\n }\n\n return plugin.status === 'active' \n ? `<button onclick=\"togglePlugin('${plugin.id}', 'deactivate')\" class=\"bg-red-600 hover:bg-red-700 text-white px-4 py-2 rounded-lg text-sm font-medium transition-colors\">Deactivate</button>`\n : `<button onclick=\"togglePlugin('${plugin.id}', 'activate')\" class=\"bg-green-600 hover:bg-green-700 text-white px-4 py-2 rounded-lg text-sm font-medium transition-colors\">Activate</button>`\n}\n\nfunction renderSettingsTab(plugin: any): string {\n const settings = plugin.settings || {}\n const isSeedDataPlugin = plugin.id === 'seed-data' || plugin.name === 'seed-data'\n const isAuthPlugin = plugin.id === 'core-auth' || plugin.name === 'core-auth'\n\n return `\n ${isSeedDataPlugin ? `\n <div class=\"backdrop-blur-md bg-black/20 rounded-xl border border-white/10 shadow-xl p-6 mb-6\">\n <div class=\"flex items-center justify-between\">\n <div>\n <h2 class=\"text-xl font-semibold text-white mb-2\">Seed Data Generator</h2>\n <p class=\"text-gray-400\">Generate realistic example data for testing and development.</p>\n </div>\n <a\n href=\"/admin/seed-data\"\n target=\"_blank\"\n class=\"inline-flex items-center gap-2 bg-green-600 hover:bg-green-700 text-white px-6 py-3 rounded-lg font-medium transition-colors\"\n >\n <svg class=\"w-5 h-5\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M12 4v16m8-8H4\"/>\n </svg>\n Open Seed Data Tool\n </a>\n </div>\n </div>\n ` : ''}\n\n <div class=\"backdrop-blur-md bg-black/20 rounded-xl border border-white/10 shadow-xl p-6\">\n ${isAuthPlugin ? `\n <h2 class=\"text-xl font-semibold text-white mb-4\">Authentication Settings</h2>\n <p class=\"text-gray-400 mb-6\">Configure user registration fields and validation rules.</p>\n ` : `\n <h2 class=\"text-xl font-semibold text-white mb-4\">Plugin Settings</h2>\n `}\n\n <form id=\"settings-form\" class=\"space-y-6\">\n ${isAuthPlugin && Object.keys(settings).length > 0\n ? renderAuthSettingsForm(settings as AuthSettings)\n : Object.keys(settings).length > 0\n ? renderSettingsFields(settings)\n : renderNoSettings(plugin)\n }\n\n ${Object.keys(settings).length > 0 ? `\n <div class=\"flex items-center justify-end pt-6 border-t border-white/10\">\n <button\n type=\"button\"\n id=\"save-button\"\n onclick=\"saveSettings()\"\n class=\"bg-blue-600 hover:bg-blue-700 text-white px-6 py-2 rounded-lg font-medium transition-colors\"\n >\n Save Settings\n </button>\n </div>\n ` : ''}\n </form>\n </div>\n `\n}\n\nfunction renderSettingsFields(settings: PluginSettings): string {\n return Object.entries(settings).map(([key, value]) => {\n const fieldId = `setting_${key}`\n const displayName = key.replace(/([A-Z])/g, ' $1').replace(/^./, str => str.toUpperCase())\n \n if (typeof value === 'boolean') {\n return `\n <div class=\"flex items-center justify-between\">\n <div>\n <label for=\"${fieldId}\" class=\"text-sm font-medium text-gray-300\">${displayName}</label>\n <p class=\"text-xs text-gray-400\">Enable or disable this feature</p>\n </div>\n <label class=\"relative inline-flex items-center cursor-pointer\">\n <input type=\"checkbox\" name=\"${fieldId}\" id=\"${fieldId}\" ${value ? 'checked' : ''} class=\"sr-only peer\">\n <div class=\"w-11 h-6 bg-gray-600 peer-focus:outline-none peer-focus:ring-4 peer-focus:ring-blue-800 rounded-full peer peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:rounded-full after:h-5 after:w-5 after:transition-all peer-checked:bg-blue-600\"></div>\n </label>\n </div>\n `\n } else if (typeof value === 'number') {\n return `\n <div>\n <label for=\"${fieldId}\" class=\"block text-sm font-medium text-gray-300 mb-2\">${displayName}</label>\n <input \n type=\"number\" \n name=\"${fieldId}\" \n id=\"${fieldId}\" \n value=\"${value}\"\n class=\"backdrop-blur-sm bg-white/10 border border-white/20 rounded-lg px-3 py-2 text-white placeholder-gray-300 focus:border-blue-400 focus:outline-none transition-colors w-full\"\n >\n </div>\n `\n } else {\n return `\n <div>\n <label for=\"${fieldId}\" class=\"block text-sm font-medium text-gray-300 mb-2\">${displayName}</label>\n <input \n type=\"text\" \n name=\"${fieldId}\" \n id=\"${fieldId}\" \n value=\"${value}\"\n class=\"backdrop-blur-sm bg-white/10 border border-white/20 rounded-lg px-3 py-2 text-white placeholder-gray-300 focus:border-blue-400 focus:outline-none transition-colors w-full\"\n >\n </div>\n `\n }\n }).join('')\n}\n\nfunction renderNoSettings(plugin: any): string {\n // Special handling for seed-data plugin\n if (plugin.id === 'seed-data' || plugin.name === 'seed-data') {\n return `\n <div class=\"text-center py-8\">\n <svg class=\"w-16 h-16 text-green-400 mx-auto mb-4\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M12 6.253v13m0-13C10.832 5.477 9.246 5 7.5 5S4.168 5.477 3 6.253v13C4.168 18.477 5.754 18 7.5 18s3.332.477 4.5 1.253m0-13C13.168 5.477 14.754 5 16.5 5c1.747 0 3.332.477 4.5 1.253v13C19.832 18.477 18.247 18 16.5 18c-1.746 0-3.332.477-4.5 1.253\"/>\n </svg>\n <h3 class=\"text-lg font-medium text-gray-300 mb-2\">Seed Data Generator</h3>\n <p class=\"text-gray-400 mb-6\">Generate realistic example data for testing and development.</p>\n <a\n href=\"/admin/seed-data\"\n class=\"inline-flex items-center gap-2 bg-green-600 hover:bg-green-700 text-white px-6 py-3 rounded-lg font-medium transition-colors\"\n >\n <svg class=\"w-5 h-5\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M12 4v16m8-8H4\"/>\n </svg>\n Generate Seed Data\n </a>\n </div>\n `\n }\n\n return `\n <div class=\"text-center py-8\">\n <svg class=\"w-12 h-12 text-gray-400 mx-auto mb-4\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z\"/>\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M15 12a3 3 0 11-6 0 3 3 0 016 0z\"/>\n </svg>\n <h3 class=\"text-lg font-medium text-gray-300 mb-2\">No Settings Available</h3>\n <p class=\"text-gray-400\">This plugin doesn't have any configurable settings.</p>\n </div>\n `\n}\n\nfunction renderActivityTab(activity: PluginActivity[]): string {\n return `\n <div class=\"backdrop-blur-md bg-black/20 rounded-xl border border-white/10 shadow-xl p-6\">\n <h2 class=\"text-xl font-semibold text-white mb-4\">Activity Log</h2>\n \n ${activity.length > 0 ? `\n <div class=\"space-y-4\">\n ${activity.map(item => `\n <div class=\"flex items-start gap-3 p-3 rounded-lg bg-white/5\">\n <div class=\"w-2 h-2 bg-blue-400 rounded-full mt-2\"></div>\n <div class=\"flex-1\">\n <div class=\"flex items-center justify-between\">\n <span class=\"text-sm font-medium text-white\">${item.action}</span>\n <span class=\"text-xs text-gray-400\">${formatTimestamp(item.timestamp)}</span>\n </div>\n <p class=\"text-sm text-gray-300 mt-1\">${item.message}</p>\n ${item.user ? `<p class=\"text-xs text-gray-400 mt-1\">by ${item.user}</p>` : ''}\n </div>\n </div>\n `).join('')}\n </div>\n ` : `\n <div class=\"text-center py-8\">\n <svg class=\"w-12 h-12 text-gray-400 mx-auto mb-4\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M9 5H7a2 2 0 00-2 2v10a2 2 0 002 2h8a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"/>\n </svg>\n <h3 class=\"text-lg font-medium text-gray-300 mb-2\">No Activity</h3>\n <p class=\"text-gray-400\">No recent activity for this plugin.</p>\n </div>\n `}\n </div>\n `\n}\n\nfunction renderInformationTab(plugin: any): string {\n return `\n <div class=\"grid grid-cols-1 lg:grid-cols-2 gap-6\">\n <!-- Plugin Details -->\n <div class=\"backdrop-blur-md bg-black/20 rounded-xl border border-white/10 shadow-xl p-6\">\n <h2 class=\"text-xl font-semibold text-white mb-4\">Plugin Details</h2>\n <div class=\"space-y-3\">\n <div class=\"flex justify-between\">\n <span class=\"text-gray-400\">Name:</span>\n <span class=\"text-white\">${plugin.displayName}</span>\n </div>\n <div class=\"flex justify-between\">\n <span class=\"text-gray-400\">Version:</span>\n <span class=\"text-white\">${plugin.version}</span>\n </div>\n <div class=\"flex justify-between\">\n <span class=\"text-gray-400\">Author:</span>\n <span class=\"text-white\">${plugin.author}</span>\n </div>\n <div class=\"flex justify-between\">\n <span class=\"text-gray-400\">Category:</span>\n <span class=\"text-white\">${plugin.category}</span>\n </div>\n <div class=\"flex justify-between\">\n <span class=\"text-gray-400\">Status:</span>\n <span class=\"text-white\">${plugin.status}</span>\n </div>\n <div class=\"flex justify-between\">\n <span class=\"text-gray-400\">Last Updated:</span>\n <span class=\"text-white\">${plugin.lastUpdated}</span>\n </div>\n </div>\n </div>\n\n <!-- Dependencies & Permissions -->\n <div class=\"backdrop-blur-md bg-black/20 rounded-xl border border-white/10 shadow-xl p-6\">\n <h2 class=\"text-xl font-semibold text-white mb-4\">Dependencies & Permissions</h2>\n \n ${plugin.dependencies && plugin.dependencies.length > 0 ? `\n <div class=\"mb-6\">\n <h3 class=\"text-sm font-medium text-gray-300 mb-2\">Dependencies:</h3>\n <div class=\"space-y-1\">\n ${plugin.dependencies.map((dep: string) => `\n <div class=\"inline-block bg-white/10 text-gray-300 text-sm px-2 py-1 rounded mr-2\">${dep}</div>\n `).join('')}\n </div>\n </div>\n ` : ''}\n\n ${plugin.permissions && plugin.permissions.length > 0 ? `\n <div>\n <h3 class=\"text-sm font-medium text-gray-300 mb-2\">Permissions:</h3>\n <div class=\"space-y-1\">\n ${plugin.permissions.map((perm: string) => `\n <div class=\"inline-block bg-white/10 text-gray-300 text-sm px-2 py-1 rounded mr-2\">${perm}</div>\n `).join('')}\n </div>\n </div>\n ` : ''}\n\n ${(!plugin.dependencies || plugin.dependencies.length === 0) && (!plugin.permissions || plugin.permissions.length === 0) ? `\n <p class=\"text-gray-400\">No dependencies or special permissions required.</p>\n ` : ''}\n </div>\n </div>\n `\n}\n\nfunction formatTimestamp(timestamp: number): string {\n const date = new Date(timestamp * 1000)\n return date.toLocaleString()\n}","import { Hono } from 'hono'\nimport { requireAuth } from '../middleware'\nimport { renderPluginsListPage, PluginsListPageData, Plugin } from '../templates/pages/admin-plugins-list.template'\nimport { renderPluginSettingsPage, PluginSettingsPageData } from '../templates/pages/admin-plugin-settings.template'\nimport { PluginService } from '../services'\n// TODO: authValidationService not yet migrated - commented out temporarily\n// import { authValidationService } from '../services/auth-validation'\nimport type { Bindings, Variables } from '../app'\n\nconst adminPluginRoutes = new Hono<{ Bindings: Bindings; Variables: Variables }>()\n\n// Apply authentication middleware\nadminPluginRoutes.use('*', requireAuth())\n\n// Available plugins registry - plugins that can be installed\nconst AVAILABLE_PLUGINS = [\n {\n id: 'third-party-faq',\n name: 'faq-plugin',\n display_name: 'FAQ System',\n description: 'Frequently Asked Questions management system with categories, search, and custom styling',\n version: '2.0.0',\n author: 'Community Developer',\n category: 'content',\n icon: '❓',\n permissions: ['manage:faqs'],\n dependencies: [],\n is_core: false\n },\n {\n id: 'demo-login-prefill',\n name: 'demo-login-plugin',\n display_name: 'Demo Login Prefill',\n description: 'Prefills login form with demo credentials (admin@sonicjs.com/sonicjs!) for easy site demonstration',\n version: '1.0.0-beta.1',\n author: 'SonicJS',\n category: 'demo',\n icon: '🎯',\n permissions: [],\n dependencies: [],\n is_core: false\n },\n {\n id: 'database-tools',\n name: 'database-tools',\n display_name: 'Database Tools',\n description: 'Database management tools including truncate, backup, and validation',\n version: '1.0.0-beta.1',\n author: 'SonicJS Team',\n category: 'system',\n icon: '🗄️',\n permissions: ['manage:database', 'admin'],\n dependencies: [],\n is_core: false\n },\n {\n id: 'seed-data',\n name: 'seed-data',\n display_name: 'Seed Data',\n description: 'Generate realistic example users and content for testing and development',\n version: '1.0.0-beta.1',\n author: 'SonicJS Team',\n category: 'development',\n icon: '🌱',\n permissions: ['admin'],\n dependencies: [],\n is_core: false\n },\n {\n id: 'quill-editor',\n name: 'quill-editor',\n display_name: 'Quill Rich Text Editor',\n description: 'Quill WYSIWYG editor integration for rich text editing. Lightweight, modern editor with customizable toolbars and dark mode support.',\n version: '1.0.0',\n author: 'SonicJS Team',\n category: 'editor',\n icon: '✍️',\n permissions: [],\n dependencies: [],\n is_core: true\n },\n {\n id: 'tinymce-plugin',\n name: 'tinymce-plugin',\n display_name: 'TinyMCE Rich Text Editor',\n description: 'Powerful WYSIWYG rich text editor for content creation. Provides a full-featured editor with formatting, media embedding, and customizable toolbars for richtext fields.',\n version: '1.0.0',\n author: 'SonicJS Team',\n category: 'editor',\n icon: '📝',\n permissions: [],\n dependencies: [],\n is_core: false\n },\n {\n id: 'easy-mdx',\n name: 'easy-mdx',\n display_name: 'EasyMDE Markdown Editor',\n description: 'Lightweight markdown editor with live preview. Provides a simple and efficient editor with markdown support for richtext fields.',\n version: '1.0.0',\n author: 'SonicJS Team',\n category: 'editor',\n icon: '📝',\n permissions: [],\n dependencies: [],\n is_core: false\n }\n]\n\n// Plugin list page\nadminPluginRoutes.get('/', async (c) => {\n try {\n const user = c.get('user')\n const db = c.env.DB\n \n // Temporarily skip permission check for admin users\n // TODO: Fix permission system\n if (user?.role !== 'admin') {\n return c.text('Access denied', 403)\n }\n \n const pluginService = new PluginService(db)\n\n // Get all installed plugins with error handling\n let installedPlugins: any[] = []\n let stats = { total: 0, active: 0, inactive: 0, errors: 0, uninstalled: 0 }\n\n try {\n installedPlugins = await pluginService.getAllPlugins()\n stats = await pluginService.getPluginStats()\n } catch (error) {\n console.error('Error loading plugins:', error)\n // Continue with empty data\n }\n\n // Get list of installed plugin IDs\n const installedPluginIds = new Set(installedPlugins.map(p => p.id))\n\n // Find uninstalled plugins\n const uninstalledPlugins = AVAILABLE_PLUGINS.filter(p => !installedPluginIds.has(p.id))\n\n // Map installed plugins to template format\n const templatePlugins: Plugin[] = installedPlugins.map(p => ({\n id: p.id,\n name: p.name,\n displayName: p.display_name,\n description: p.description,\n version: p.version,\n author: p.author,\n status: p.status,\n category: p.category,\n icon: p.icon,\n downloadCount: p.download_count,\n rating: p.rating,\n lastUpdated: formatLastUpdated(p.last_updated),\n dependencies: p.dependencies,\n permissions: p.permissions,\n isCore: p.is_core\n }))\n\n // Add uninstalled plugins to the list\n const uninstalledTemplatePlugins: Plugin[] = uninstalledPlugins.map(p => ({\n id: p.id,\n name: p.name,\n displayName: p.display_name,\n description: p.description,\n version: p.version,\n author: p.author,\n status: 'uninstalled' as const,\n category: p.category,\n icon: p.icon,\n downloadCount: 0,\n rating: 0,\n lastUpdated: 'Not installed',\n dependencies: p.dependencies,\n permissions: p.permissions,\n isCore: p.is_core\n }))\n\n // Combine installed and uninstalled plugins\n const allPlugins = [...templatePlugins, ...uninstalledTemplatePlugins]\n\n // Update stats with uninstalled count\n stats.uninstalled = uninstalledPlugins.length\n stats.total = installedPlugins.length + uninstalledPlugins.length\n\n const pageData: PluginsListPageData = {\n plugins: allPlugins,\n stats,\n user: {\n name: user?.email || 'User',\n email: user?.email || '',\n role: user?.role || 'user'\n },\n version: c.get('appVersion')\n }\n\n return c.html(renderPluginsListPage(pageData))\n } catch (error) {\n console.error('Error loading plugins page:', error)\n return c.text('Internal server error', 500)\n }\n})\n\n// Get plugin settings page\nadminPluginRoutes.get('/:id', async (c) => {\n try {\n const user = c.get('user')\n const db = c.env.DB\n const pluginId = c.req.param('id')\n \n // Check authorization\n if (user?.role !== 'admin') {\n return c.redirect('/admin/plugins')\n }\n \n const pluginService = new PluginService(db)\n const plugin = await pluginService.getPlugin(pluginId)\n \n if (!plugin) {\n return c.text('Plugin not found', 404)\n }\n \n // Get activity log\n const activity = await pluginService.getPluginActivity(pluginId, 20)\n \n // Map plugin data to template format\n const templatePlugin = {\n id: plugin.id,\n name: plugin.name,\n displayName: plugin.display_name,\n description: plugin.description,\n version: plugin.version,\n author: plugin.author,\n status: plugin.status,\n category: plugin.category,\n icon: plugin.icon,\n downloadCount: plugin.download_count,\n rating: plugin.rating,\n lastUpdated: formatLastUpdated(plugin.last_updated),\n dependencies: plugin.dependencies,\n permissions: plugin.permissions,\n isCore: plugin.is_core,\n settings: plugin.settings\n }\n \n // Map activity data\n const templateActivity = (activity || []).map(item => ({\n id: item.id,\n action: item.action,\n message: item.message,\n timestamp: item.timestamp,\n user: item.user_email\n }))\n \n const pageData: PluginSettingsPageData = {\n plugin: templatePlugin,\n activity: templateActivity,\n user: {\n name: user?.email || 'User',\n email: user?.email || '',\n role: user?.role || 'user'\n }\n }\n \n return c.html(renderPluginSettingsPage(pageData))\n } catch (error) {\n console.error('Error getting plugin settings page:', error)\n return c.text('Internal server error', 500)\n }\n})\n\n// Activate plugin\nadminPluginRoutes.post('/:id/activate', async (c) => {\n try {\n const user = c.get('user')\n const db = c.env.DB\n const pluginId = c.req.param('id')\n \n // Temporarily skip permission check for admin users\n if (user?.role !== 'admin') {\n return c.json({ error: 'Access denied' }, 403)\n }\n \n const pluginService = new PluginService(db)\n await pluginService.activatePlugin(pluginId)\n \n return c.json({ success: true })\n } catch (error) {\n console.error('Error activating plugin:', error)\n const message = error instanceof Error ? error.message : 'Failed to activate plugin'\n return c.json({ error: message }, 400)\n }\n})\n\n// Deactivate plugin\nadminPluginRoutes.post('/:id/deactivate', async (c) => {\n try {\n const user = c.get('user')\n const db = c.env.DB\n const pluginId = c.req.param('id')\n \n // Temporarily skip permission check for admin users\n if (user?.role !== 'admin') {\n return c.json({ error: 'Access denied' }, 403)\n }\n \n const pluginService = new PluginService(db)\n await pluginService.deactivatePlugin(pluginId)\n \n return c.json({ success: true })\n } catch (error) {\n console.error('Error deactivating plugin:', error)\n const message = error instanceof Error ? error.message : 'Failed to deactivate plugin'\n return c.json({ error: message }, 400)\n }\n})\n\n// Install plugin\nadminPluginRoutes.post('/install', async (c) => {\n try {\n const user = c.get('user')\n const db = c.env.DB\n \n // Temporarily skip permission check for admin users\n if (user?.role !== 'admin') {\n return c.json({ error: 'Access denied' }, 403)\n }\n \n const body = await c.req.json()\n \n const pluginService = new PluginService(db)\n \n // Handle FAQ plugin installation\n if (body.name === 'faq-plugin') {\n const faqPlugin = await pluginService.installPlugin({\n id: 'third-party-faq',\n name: 'faq-plugin',\n display_name: 'FAQ System',\n description: 'Frequently Asked Questions management system with categories, search, and custom styling',\n version: '2.0.0',\n author: 'Community Developer',\n category: 'content',\n icon: '❓',\n permissions: ['manage:faqs'],\n dependencies: [],\n settings: {\n enableSearch: true,\n enableCategories: true,\n questionsPerPage: 10\n }\n })\n\n return c.json({ success: true, plugin: faqPlugin })\n }\n\n // Handle Demo Login plugin installation\n if (body.name === 'demo-login-plugin') {\n const demoPlugin = await pluginService.installPlugin({\n id: 'demo-login-prefill',\n name: 'demo-login-plugin',\n display_name: 'Demo Login Prefill',\n description: 'Prefills login form with demo credentials (admin@sonicjs.com/sonicjs!) for easy site demonstration',\n version: '1.0.0-beta.1',\n author: 'SonicJS',\n category: 'demo',\n icon: '🎯',\n permissions: [],\n dependencies: [],\n settings: {\n enableNotice: true,\n demoEmail: 'admin@sonicjs.com',\n demoPassword: 'sonicjs!'\n }\n })\n\n return c.json({ success: true, plugin: demoPlugin })\n }\n\n // Handle core Authentication System plugin installation\n if (body.name === 'core-auth') {\n const authPlugin = await pluginService.installPlugin({\n id: 'core-auth',\n name: 'core-auth',\n display_name: 'Authentication System',\n description: 'Core authentication and user management system',\n version: '1.0.0-beta.1',\n author: 'SonicJS Team',\n category: 'security',\n icon: '🔐',\n permissions: ['manage:users', 'manage:roles', 'manage:permissions'],\n dependencies: [],\n is_core: true,\n settings: {}\n })\n\n return c.json({ success: true, plugin: authPlugin })\n }\n\n // Handle core Media Manager plugin installation\n if (body.name === 'core-media') {\n const mediaPlugin = await pluginService.installPlugin({\n id: 'core-media',\n name: 'core-media',\n display_name: 'Media Manager',\n description: 'Core media upload and management system',\n version: '1.0.0-beta.1',\n author: 'SonicJS Team',\n category: 'media',\n icon: '📸',\n permissions: ['manage:media', 'upload:files'],\n dependencies: [],\n is_core: true,\n settings: {}\n })\n\n return c.json({ success: true, plugin: mediaPlugin })\n }\n\n // Handle core Workflow Engine plugin installation\n if (body.name === 'core-workflow') {\n const workflowPlugin = await pluginService.installPlugin({\n id: 'core-workflow',\n name: 'core-workflow',\n display_name: 'Workflow Engine',\n description: 'Content workflow and approval system',\n version: '1.0.0-beta.1',\n author: 'SonicJS Team',\n category: 'content',\n icon: '🔄',\n permissions: ['manage:workflows', 'approve:content'],\n dependencies: [],\n is_core: true,\n settings: {}\n })\n\n return c.json({ success: true, plugin: workflowPlugin })\n }\n\n // Handle Database Tools plugin installation\n if (body.name === 'database-tools') {\n const databaseToolsPlugin = await pluginService.installPlugin({\n id: 'database-tools',\n name: 'database-tools',\n display_name: 'Database Tools',\n description: 'Database management tools including truncate, backup, and validation',\n version: '1.0.0-beta.1',\n author: 'SonicJS Team',\n category: 'system',\n icon: '🗄️',\n permissions: ['manage:database', 'admin'],\n dependencies: [],\n is_core: false,\n settings: {\n enableTruncate: true,\n enableBackup: true,\n enableValidation: true,\n requireConfirmation: true\n }\n })\n\n return c.json({ success: true, plugin: databaseToolsPlugin })\n }\n\n // Handle Seed Data plugin installation\n if (body.name === 'seed-data') {\n const seedDataPlugin = await pluginService.installPlugin({\n id: 'seed-data',\n name: 'seed-data',\n display_name: 'Seed Data',\n description: 'Generate realistic example users and content for testing and development',\n version: '1.0.0-beta.1',\n author: 'SonicJS Team',\n category: 'development',\n icon: '🌱',\n permissions: ['admin'],\n dependencies: [],\n is_core: false,\n settings: {\n userCount: 20,\n contentCount: 200,\n defaultPassword: 'password123'\n }\n })\n\n return c.json({ success: true, plugin: seedDataPlugin })\n }\n\n // Handle Quill Editor plugin installation\n if (body.name === 'quill-editor') {\n const quillPlugin = await pluginService.installPlugin({\n id: 'quill-editor',\n name: 'quill-editor',\n display_name: 'Quill Rich Text Editor',\n description: 'Quill WYSIWYG editor integration for rich text editing. Lightweight, modern editor with customizable toolbars and dark mode support.',\n version: '1.0.0',\n author: 'SonicJS Team',\n category: 'editor',\n icon: '✍️',\n permissions: [],\n dependencies: [],\n is_core: true,\n settings: {\n version: '2.0.2',\n defaultHeight: 300,\n defaultToolbar: 'full',\n theme: 'snow'\n }\n })\n\n return c.json({ success: true, plugin: quillPlugin })\n }\n\n // Handle TinyMCE plugin installation\n if (body.name === 'tinymce-plugin') {\n const tinymcePlugin = await pluginService.installPlugin({\n id: 'tinymce-plugin',\n name: 'tinymce-plugin',\n display_name: 'TinyMCE Rich Text Editor',\n description: 'Powerful WYSIWYG rich text editor for content creation. Provides a full-featured editor with formatting, media embedding, and customizable toolbars for richtext fields.',\n version: '1.0.0',\n author: 'SonicJS Team',\n category: 'editor',\n icon: '📝',\n permissions: [],\n dependencies: [],\n is_core: false,\n settings: {\n apiKey: 'no-api-key',\n defaultHeight: 300,\n defaultToolbar: 'full',\n skin: 'oxide-dark'\n }\n })\n\n return c.json({ success: true, plugin: tinymcePlugin })\n }\n\n // Handle Easy MDX plugin installation\n if (body.name === 'easy-mdx') {\n const easyMdxPlugin = await pluginService.installPlugin({\n id: 'easy-mdx',\n name: 'easy-mdx',\n display_name: 'EasyMDE Markdown Editor',\n description: 'Lightweight markdown editor with live preview. Provides a simple and efficient editor with markdown support for richtext fields.',\n version: '1.0.0',\n author: 'SonicJS Team',\n category: 'editor',\n icon: '📝',\n permissions: [],\n dependencies: [],\n is_core: false,\n settings: {\n defaultHeight: 400,\n theme: 'dark',\n toolbar: 'full',\n placeholder: 'Start writing your content...'\n }\n })\n\n return c.json({ success: true, plugin: easyMdxPlugin })\n }\n\n return c.json({ error: 'Plugin not found in registry' }, 404)\n } catch (error) {\n console.error('Error installing plugin:', error)\n const message = error instanceof Error ? error.message : 'Failed to install plugin'\n return c.json({ error: message }, 400)\n }\n})\n\n// Uninstall plugin\nadminPluginRoutes.post('/:id/uninstall', async (c) => {\n try {\n const user = c.get('user')\n const db = c.env.DB\n const pluginId = c.req.param('id')\n \n // Temporarily skip permission check for admin users\n if (user?.role !== 'admin') {\n return c.json({ error: 'Access denied' }, 403)\n }\n \n const pluginService = new PluginService(db)\n await pluginService.uninstallPlugin(pluginId)\n \n return c.json({ success: true })\n } catch (error) {\n console.error('Error uninstalling plugin:', error)\n const message = error instanceof Error ? error.message : 'Failed to uninstall plugin'\n return c.json({ error: message }, 400)\n }\n})\n\n// Update plugin settings\nadminPluginRoutes.post('/:id/settings', async (c) => {\n try {\n const user = c.get('user')\n const db = c.env.DB\n const pluginId = c.req.param('id')\n\n // Temporarily skip permission check for admin users\n if (user?.role !== 'admin') {\n return c.json({ error: 'Access denied' }, 403)\n }\n\n const settings = await c.req.json()\n\n const pluginService = new PluginService(db)\n await pluginService.updatePluginSettings(pluginId, settings)\n\n // TODO: Clear auth validation cache if updating core-auth plugin\n // Commented out until authValidationService is migrated\n // if (pluginId === 'core-auth') {\n // authValidationService.clearCache()\n // console.log('[AuthSettings] Cache cleared after updating authentication settings')\n // }\n\n return c.json({ success: true })\n } catch (error) {\n console.error('Error updating plugin settings:', error)\n const message = error instanceof Error ? error.message : 'Failed to update settings'\n return c.json({ error: message }, 400)\n }\n})\n\n// Helper function to format last updated time\nfunction formatLastUpdated(timestamp: number): string {\n const now = Date.now() / 1000\n const diff = now - timestamp\n\n if (diff < 60) return 'just now'\n if (diff < 3600) return `${Math.floor(diff / 60)} minutes ago`\n if (diff < 86400) return `${Math.floor(diff / 3600)} hours ago`\n if (diff < 604800) return `${Math.floor(diff / 86400)} days ago`\n if (diff < 2592000) return `${Math.floor(diff / 604800)} weeks ago`\n return `${Math.floor(diff / 2592000)} months ago`\n}\n\nexport { adminPluginRoutes }\n","import { renderAdminLayoutCatalyst, AdminLayoutCatalystData } from '../layouts/admin-layout-catalyst.template'\n\ninterface BaseUser {\n name: string\n email: string\n role: string\n}\n\nexport interface LogEntry {\n id: string\n level: string\n category: string\n message: string\n data?: any\n userId?: string\n sessionId?: string\n requestId?: string\n ipAddress?: string\n userAgent?: string\n method?: string\n url?: string\n statusCode?: number\n duration?: number\n stackTrace?: string\n tags: string[]\n source?: string\n createdAt: Date\n formattedDate: string\n formattedDuration?: string\n levelClass: string\n categoryClass: string\n}\n\nexport interface LogsListPageData {\n logs: LogEntry[]\n pagination: {\n currentPage: number\n totalPages: number\n totalItems: number\n itemsPerPage: number\n startItem: number\n endItem: number\n baseUrl: string\n }\n filters: {\n level: string\n category: string\n search: string\n startDate: string\n endDate: string\n source: string\n }\n user?: BaseUser\n}\n\nexport function renderLogsListPage(data: LogsListPageData) {\n const { logs, pagination, filters, user } = data\n\n const content = `\n <div>\n <div class=\"sm:flex sm:items-center sm:justify-between mb-6\">\n <div class=\"sm:flex-auto\">\n <h1 class=\"text-2xl/8 font-semibold text-zinc-950 dark:text-white sm:text-xl/8\">System Logs</h1>\n <p class=\"mt-2 text-sm/6 text-zinc-500 dark:text-zinc-400\">\n Monitor and analyze system activity, errors, and performance metrics.\n </p>\n </div>\n <div class=\"mt-4 sm:mt-0 sm:ml-16 flex gap-x-2\">\n <a\n href=\"/admin/logs/config\"\n class=\"inline-flex items-center justify-center rounded-lg bg-white dark:bg-zinc-800 px-3.5 py-2.5 text-sm font-semibold text-zinc-950 dark:text-white hover:bg-zinc-50 dark:hover:bg-zinc-700 ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 transition-colors shadow-sm\"\n >\n Configure\n </a>\n <a\n href=\"/admin/logs/export?${new URLSearchParams(filters).toString()}\"\n class=\"inline-flex items-center justify-center rounded-lg bg-zinc-950 dark:bg-white px-3.5 py-2.5 text-sm font-semibold text-white dark:text-zinc-950 hover:bg-zinc-800 dark:hover:bg-zinc-100 transition-colors shadow-sm\"\n >\n Export\n </a>\n </div>\n </div>\n\n <!-- Filters -->\n <div class=\"relative rounded-xl overflow-hidden mb-6\">\n <!-- Gradient Background -->\n <div class=\"absolute inset-0 bg-gradient-to-r from-cyan-500/10 via-blue-500/10 to-purple-500/10 dark:from-cyan-400/20 dark:via-blue-400/20 dark:to-purple-400/20\"></div>\n\n <div class=\"relative bg-white/80 dark:bg-zinc-900/80 backdrop-blur-xl shadow-sm ring-1 ring-zinc-950/5 dark:ring-white/10\">\n <div class=\"px-6 py-5\">\n <form method=\"GET\" action=\"/admin/logs\" class=\"space-y-4\">\n <div class=\"grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-4\">\n <div class=\"relative group\">\n <label for=\"search\" class=\"block text-sm font-medium text-zinc-950 dark:text-white mb-2\">Search</label>\n <div class=\"relative\">\n <div class=\"absolute left-3.5 top-2.5 flex items-center justify-center w-5 h-5 rounded-full bg-gradient-to-br from-cyan-400 to-blue-500 dark:from-cyan-300 dark:to-blue-400 opacity-90 group-focus-within:opacity-100 transition-opacity\">\n <svg class=\"h-3 w-3 text-white\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\" stroke-width=\"2.5\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z\"/>\n </svg>\n </div>\n <input\n type=\"text\"\n name=\"search\"\n id=\"search\"\n value=\"${filters.search}\"\n placeholder=\"Search messages...\"\n class=\"w-full rounded-full bg-transparent pl-11 pr-4 py-2 text-sm text-zinc-950 dark:text-white placeholder-zinc-500 dark:placeholder-zinc-400 border-2 border-cyan-200/50 dark:border-cyan-700/50 focus:outline-none focus:border-cyan-500 dark:focus:border-cyan-400 focus:shadow-lg focus:shadow-cyan-500/20 dark:focus:shadow-cyan-400/20 transition-all duration-300\"\n />\n </div>\n </div>\n\n <div>\n <label for=\"level\" class=\"block text-sm font-medium text-zinc-950 dark:text-white mb-2\">Level</label>\n <select\n name=\"level\"\n id=\"level\"\n class=\"w-full rounded-lg bg-white/90 dark:bg-zinc-800/90 backdrop-blur-sm px-4 py-2 text-sm text-zinc-950 dark:text-white border-2 border-cyan-200/50 dark:border-cyan-700/50 focus:outline-none focus:border-cyan-500 dark:focus:border-cyan-400 focus:shadow-lg focus:shadow-cyan-500/20 dark:focus:shadow-cyan-400/20 transition-all duration-300\"\n >\n <option value=\"\">All Levels</option>\n <option value=\"debug\" ${filters.level === 'debug' ? 'selected' : ''}>Debug</option>\n <option value=\"info\" ${filters.level === 'info' ? 'selected' : ''}>Info</option>\n <option value=\"warn\" ${filters.level === 'warn' ? 'selected' : ''}>Warning</option>\n <option value=\"error\" ${filters.level === 'error' ? 'selected' : ''}>Error</option>\n <option value=\"fatal\" ${filters.level === 'fatal' ? 'selected' : ''}>Fatal</option>\n </select>\n </div>\n\n <div>\n <label for=\"category\" class=\"block text-sm font-medium text-zinc-950 dark:text-white mb-2\">Category</label>\n <select\n name=\"category\"\n id=\"category\"\n class=\"w-full rounded-lg bg-white/90 dark:bg-zinc-800/90 backdrop-blur-sm px-4 py-2 text-sm text-zinc-950 dark:text-white border-2 border-cyan-200/50 dark:border-cyan-700/50 focus:outline-none focus:border-cyan-500 dark:focus:border-cyan-400 focus:shadow-lg focus:shadow-cyan-500/20 dark:focus:shadow-cyan-400/20 transition-all duration-300\"\n >\n <option value=\"\">All Categories</option>\n <option value=\"auth\" ${filters.category === 'auth' ? 'selected' : ''}>Authentication</option>\n <option value=\"api\" ${filters.category === 'api' ? 'selected' : ''}>API</option>\n <option value=\"workflow\" ${filters.category === 'workflow' ? 'selected' : ''}>Workflow</option>\n <option value=\"plugin\" ${filters.category === 'plugin' ? 'selected' : ''}>Plugin</option>\n <option value=\"media\" ${filters.category === 'media' ? 'selected' : ''}>Media</option>\n <option value=\"system\" ${filters.category === 'system' ? 'selected' : ''}>System</option>\n <option value=\"security\" ${filters.category === 'security' ? 'selected' : ''}>Security</option>\n <option value=\"error\" ${filters.category === 'error' ? 'selected' : ''}>Error</option>\n </select>\n </div>\n\n <div>\n <label for=\"source\" class=\"block text-sm font-medium text-zinc-950 dark:text-white mb-2\">Source</label>\n <input\n type=\"text\"\n name=\"source\"\n id=\"source\"\n value=\"${filters.source}\"\n placeholder=\"e.g., http-middleware\"\n class=\"w-full rounded-lg bg-white/90 dark:bg-zinc-800/90 backdrop-blur-sm px-4 py-2 text-sm text-zinc-950 dark:text-white placeholder-zinc-500 dark:placeholder-zinc-400 border-2 border-cyan-200/50 dark:border-cyan-700/50 focus:outline-none focus:border-cyan-500 dark:focus:border-cyan-400 focus:shadow-lg focus:shadow-cyan-500/20 dark:focus:shadow-cyan-400/20 transition-all duration-300\"\n />\n </div>\n\n <div>\n <label for=\"start_date\" class=\"block text-sm font-medium text-zinc-950 dark:text-white mb-2\">Start Date</label>\n <input\n type=\"datetime-local\"\n name=\"start_date\"\n id=\"start_date\"\n value=\"${filters.startDate}\"\n class=\"w-full rounded-lg bg-white/90 dark:bg-zinc-800/90 backdrop-blur-sm px-4 py-2 text-sm text-zinc-950 dark:text-white border-2 border-cyan-200/50 dark:border-cyan-700/50 focus:outline-none focus:border-cyan-500 dark:focus:border-cyan-400 focus:shadow-lg focus:shadow-cyan-500/20 dark:focus:shadow-cyan-400/20 transition-all duration-300\"\n />\n </div>\n\n <div>\n <label for=\"end_date\" class=\"block text-sm font-medium text-zinc-950 dark:text-white mb-2\">End Date</label>\n <input\n type=\"datetime-local\"\n name=\"end_date\"\n id=\"end_date\"\n value=\"${filters.endDate}\"\n class=\"w-full rounded-lg bg-white/90 dark:bg-zinc-800/90 backdrop-blur-sm px-4 py-2 text-sm text-zinc-950 dark:text-white border-2 border-cyan-200/50 dark:border-cyan-700/50 focus:outline-none focus:border-cyan-500 dark:focus:border-cyan-400 focus:shadow-lg focus:shadow-cyan-500/20 dark:focus:shadow-cyan-400/20 transition-all duration-300\"\n />\n </div>\n\n <div class=\"sm:col-span-2 flex items-end gap-x-2\">\n <button\n type=\"submit\"\n class=\"inline-flex items-center justify-center rounded-lg bg-zinc-950 dark:bg-white px-3.5 py-2.5 text-sm font-semibold text-white dark:text-zinc-950 hover:bg-zinc-800 dark:hover:bg-zinc-100 transition-colors shadow-sm\"\n >\n Apply Filters\n </button>\n <a\n href=\"/admin/logs\"\n class=\"inline-flex items-center justify-center rounded-lg bg-white dark:bg-zinc-800 px-3.5 py-2.5 text-sm font-semibold text-zinc-950 dark:text-white hover:bg-zinc-50 dark:hover:bg-zinc-700 ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 transition-colors shadow-sm\"\n >\n Clear\n </a>\n </div>\n </div>\n\n <div class=\"flex items-center justify-end pt-2\">\n <span class=\"text-sm/6 font-medium text-zinc-700 dark:text-zinc-300 px-3 py-1.5 rounded-full bg-white/60 dark:bg-zinc-800/60 backdrop-blur-sm\">${pagination.totalItems} ${pagination.totalItems === 1 ? 'entry' : 'entries'}</span>\n </div>\n </form>\n </div>\n </div>\n </div>\n\n <!-- Logs Table -->\n <div class=\"rounded-xl bg-white dark:bg-zinc-900 shadow-sm ring-1 ring-zinc-950/5 dark:ring-white/10 overflow-hidden\">\n <div class=\"overflow-x-auto\">\n <table class=\"min-w-full\">\n <thead>\n <tr class=\"border-b border-zinc-950/5 dark:border-white/5\">\n <th scope=\"col\" class=\"px-4 py-3.5 text-left text-sm font-semibold text-zinc-950 dark:text-white sm:pl-6\">\n Level\n </th>\n <th scope=\"col\" class=\"px-4 py-3.5 text-left text-sm font-semibold text-zinc-950 dark:text-white\">\n Category\n </th>\n <th scope=\"col\" class=\"px-4 py-3.5 text-left text-sm font-semibold text-zinc-950 dark:text-white\">\n Message\n </th>\n <th scope=\"col\" class=\"px-4 py-3.5 text-left text-sm font-semibold text-zinc-950 dark:text-white\">\n Source\n </th>\n <th scope=\"col\" class=\"px-4 py-3.5 text-left text-sm font-semibold text-zinc-950 dark:text-white\">\n Time\n </th>\n <th scope=\"col\" class=\"relative px-4 py-3.5 sm:pr-6\">\n <span class=\"sr-only\">Actions</span>\n </th>\n </tr>\n </thead>\n <tbody>\n ${logs.map(log => `\n <tr class=\"border-t border-zinc-950/5 dark:border-white/5 hover:bg-gradient-to-r hover:from-cyan-50/50 hover:via-blue-50/30 hover:to-purple-50/50 dark:hover:from-cyan-900/20 dark:hover:via-blue-900/10 dark:hover:to-purple-900/20 hover:shadow-sm hover:shadow-cyan-500/5 dark:hover:shadow-cyan-400/5 transition-all duration-300\">\n <td class=\"px-4 py-4 whitespace-nowrap sm:pl-6\">\n <span class=\"inline-flex items-center rounded-md px-2.5 py-1 text-sm font-medium ring-1 ring-inset ${log.levelClass}\">\n ${log.level}\n </span>\n </td>\n <td class=\"px-4 py-4 whitespace-nowrap\">\n <span class=\"inline-flex items-center rounded-md px-2.5 py-1 text-sm font-medium ring-1 ring-inset ${log.categoryClass}\">\n ${log.category}\n </span>\n </td>\n <td class=\"px-4 py-4\">\n <div class=\"text-sm max-w-md\">\n <div class=\"truncate text-zinc-950 dark:text-white\" title=\"${log.message}\">${log.message}</div>\n ${log.url ? `<div class=\"text-xs text-zinc-500 dark:text-zinc-400 truncate mt-1\">${log.method} ${log.url}</div>` : ''}\n ${log.duration ? `<div class=\"text-xs text-zinc-500 dark:text-zinc-400 mt-1\">${log.formattedDuration}</div>` : ''}\n </div>\n </td>\n <td class=\"px-4 py-4 whitespace-nowrap text-sm text-zinc-500 dark:text-zinc-400\">\n ${log.source || '-'}\n </td>\n <td class=\"px-4 py-4 whitespace-nowrap text-sm text-zinc-500 dark:text-zinc-400\">\n ${log.formattedDate}\n </td>\n <td class=\"px-4 py-4 whitespace-nowrap text-right text-sm font-medium sm:pr-6\">\n <a href=\"/admin/logs/${log.id}\" class=\"text-cyan-600 dark:text-cyan-400 hover:text-cyan-700 dark:hover:text-cyan-300 transition-colors\">\n View Details\n </a>\n </td>\n </tr>\n `).join('')}\n </tbody>\n </table>\n </div>\n\n ${logs.length === 0 ? `\n <div class=\"text-center py-12\">\n <svg class=\"mx-auto h-12 w-12 text-zinc-400 dark:text-zinc-500\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z\" />\n </svg>\n <h3 class=\"mt-2 text-sm font-medium text-zinc-950 dark:text-white\">No log entries</h3>\n <p class=\"mt-1 text-sm text-zinc-500 dark:text-zinc-400\">No log entries found matching your criteria.</p>\n </div>\n ` : ''}\n </div>\n\n <!-- Pagination -->\n ${pagination.totalPages > 1 ? `\n <div class=\"mt-6 flex items-center justify-between\">\n <div class=\"flex-1 flex justify-between sm:hidden\">\n ${pagination.currentPage > 1 ? `\n <a\n href=\"${pagination.baseUrl}?${new URLSearchParams({...filters, page: (pagination.currentPage - 1).toString()}).toString()}\"\n class=\"relative inline-flex items-center px-4 py-2 rounded-lg bg-white dark:bg-zinc-800 text-sm font-medium text-zinc-950 dark:text-white hover:bg-zinc-50 dark:hover:bg-zinc-700 ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 transition-colors\"\n >\n Previous\n </a>\n ` : `\n <span class=\"relative inline-flex items-center px-4 py-2 rounded-lg text-sm font-medium text-zinc-400 dark:text-zinc-600 bg-zinc-100 dark:bg-zinc-800 cursor-not-allowed\">\n Previous\n </span>\n `}\n ${pagination.currentPage < pagination.totalPages ? `\n <a\n href=\"${pagination.baseUrl}?${new URLSearchParams({...filters, page: (pagination.currentPage + 1).toString()}).toString()}\"\n class=\"ml-3 relative inline-flex items-center px-4 py-2 rounded-lg bg-white dark:bg-zinc-800 text-sm font-medium text-zinc-950 dark:text-white hover:bg-zinc-50 dark:hover:bg-zinc-700 ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 transition-colors\"\n >\n Next\n </a>\n ` : `\n <span class=\"ml-3 relative inline-flex items-center px-4 py-2 rounded-lg text-sm font-medium text-zinc-400 dark:text-zinc-600 bg-zinc-100 dark:bg-zinc-800 cursor-not-allowed\">\n Next\n </span>\n `}\n </div>\n <div class=\"hidden sm:flex-1 sm:flex sm:items-center sm:justify-between\">\n <div>\n <p class=\"text-sm text-zinc-700 dark:text-zinc-300\">\n Showing <span class=\"font-medium\">${pagination.startItem}</span> to <span class=\"font-medium\">${pagination.endItem}</span> of{' '}\n <span class=\"font-medium\">${pagination.totalItems}</span> results\n </p>\n </div>\n <div>\n <nav class=\"relative z-0 inline-flex rounded-lg shadow-sm -space-x-px\" aria-label=\"Pagination\">\n ${pagination.currentPage > 1 ? `\n <a\n href=\"${pagination.baseUrl}?${new URLSearchParams({...filters, page: (pagination.currentPage - 1).toString()}).toString()}\"\n class=\"relative inline-flex items-center px-2 py-2 rounded-l-lg bg-white dark:bg-zinc-800 text-sm font-medium text-zinc-500 dark:text-zinc-400 hover:bg-zinc-50 dark:hover:bg-zinc-700 ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 transition-colors\"\n >\n <span class=\"sr-only\">Previous</span>\n <svg class=\"h-5 w-5\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 20 20\" fill=\"currentColor\" aria-hidden=\"true\">\n <path fill-rule=\"evenodd\" d=\"M12.707 5.293a1 1 0 010 1.414L9.414 10l3.293 3.293a1 1 0 01-1.414 1.414l-4-4a1 1 0 010-1.414l4-4a1 1 0 011.414 0z\" clip-rule=\"evenodd\" />\n </svg>\n </a>\n ` : ''}\n\n ${Array.from({ length: Math.min(10, pagination.totalPages) }, (_, i) => {\n const page = Math.max(1, Math.min(pagination.totalPages - 9, pagination.currentPage - 5)) + i\n if (page > pagination.totalPages) return ''\n\n return `\n <a\n href=\"${pagination.baseUrl}?${new URLSearchParams({...filters, page: page.toString()}).toString()}\"\n class=\"relative inline-flex items-center px-4 py-2 text-sm font-medium ring-1 ring-inset transition-colors ${\n page === pagination.currentPage\n ? 'z-10 bg-cyan-50 dark:bg-cyan-900/20 ring-cyan-600 dark:ring-cyan-400 text-cyan-600 dark:text-cyan-400'\n : 'bg-white dark:bg-zinc-800 ring-zinc-950/10 dark:ring-white/10 text-zinc-500 dark:text-zinc-400 hover:bg-zinc-50 dark:hover:bg-zinc-700'\n }\"\n >\n ${page}\n </a>\n `\n }).join('')}\n\n ${pagination.currentPage < pagination.totalPages ? `\n <a\n href=\"${pagination.baseUrl}?${new URLSearchParams({...filters, page: (pagination.currentPage + 1).toString()}).toString()}\"\n class=\"relative inline-flex items-center px-2 py-2 rounded-r-lg bg-white dark:bg-zinc-800 text-sm font-medium text-zinc-500 dark:text-zinc-400 hover:bg-zinc-50 dark:hover:bg-zinc-700 ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 transition-colors\"\n >\n <span class=\"sr-only\">Next</span>\n <svg class=\"h-5 w-5\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 20 20\" fill=\"currentColor\" aria-hidden=\"true\">\n <path fill-rule=\"evenodd\" d=\"M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z\" clip-rule=\"evenodd\" />\n </svg>\n </a>\n ` : ''}\n </nav>\n </div>\n </div>\n </div>\n ` : ''}\n </div>\n `\n\n const layoutData: AdminLayoutCatalystData = {\n title: 'System Logs',\n pageTitle: 'System Logs',\n currentPath: '/admin/logs',\n user,\n content\n }\n\n return renderAdminLayoutCatalyst(layoutData)\n}","import { html } from 'hono/html'\nimport { adminLayoutV2 } from '../layouts/admin-layout-v2.template'\nimport { LogEntry } from './admin-logs-list.template'\n\ninterface BaseUser {\n name: string\n email: string\n role: string\n}\n\nexport interface LogDetailsPageData {\n log: LogEntry\n user?: BaseUser\n}\n\nexport function renderLogDetailsPage(data: LogDetailsPageData) {\n const { log, user } = data\n\n const content = html`\n <div class=\"px-4 sm:px-6 lg:px-8\">\n <div class=\"sm:flex sm:items-center\">\n <div class=\"sm:flex-auto\">\n <nav class=\"mb-4\">\n <a href=\"/admin/logs\" class=\"text-indigo-600 hover:text-indigo-900\">\n ← Back to Logs\n </a>\n </nav>\n <h1 class=\"text-2xl font-semibold text-gray-900\">Log Details</h1>\n <p class=\"mt-2 text-sm text-gray-700\">\n Detailed information for log entry ${log.id}\n </p>\n </div>\n </div>\n\n <div class=\"mt-6 bg-white shadow rounded-lg overflow-hidden\">\n <div class=\"px-6 py-4 border-b border-gray-200\">\n <div class=\"flex items-center justify-between\">\n <h2 class=\"text-lg font-medium text-gray-900\">Log Entry Information</h2>\n <div class=\"flex items-center space-x-2\">\n <span class=\"px-2 inline-flex text-xs leading-5 font-semibold rounded-full ${log.levelClass}\">\n ${log.level}\n </span>\n <span class=\"px-2 inline-flex text-xs leading-5 font-semibold rounded-full ${log.categoryClass}\">\n ${log.category}\n </span>\n </div>\n </div>\n </div>\n \n <div class=\"px-6 py-4\">\n <dl class=\"grid grid-cols-1 gap-x-4 gap-y-6 sm:grid-cols-2\">\n <div>\n <dt class=\"text-sm font-medium text-gray-500\">ID</dt>\n <dd class=\"mt-1 text-sm text-gray-900 font-mono\">${log.id}</dd>\n </div>\n \n <div>\n <dt class=\"text-sm font-medium text-gray-500\">Timestamp</dt>\n <dd class=\"mt-1 text-sm text-gray-900\">${log.formattedDate}</dd>\n </div>\n \n <div>\n <dt class=\"text-sm font-medium text-gray-500\">Level</dt>\n <dd class=\"mt-1\">\n <span class=\"px-2 inline-flex text-xs leading-5 font-semibold rounded-full ${log.levelClass}\">\n ${log.level}\n </span>\n </dd>\n </div>\n \n <div>\n <dt class=\"text-sm font-medium text-gray-500\">Category</dt>\n <dd class=\"mt-1\">\n <span class=\"px-2 inline-flex text-xs leading-5 font-semibold rounded-full ${log.categoryClass}\">\n ${log.category}\n </span>\n </dd>\n </div>\n \n ${log.source ? html`\n <div>\n <dt class=\"text-sm font-medium text-gray-500\">Source</dt>\n <dd class=\"mt-1 text-sm text-gray-900\">${log.source}</dd>\n </div>\n ` : ''}\n \n ${log.userId ? html`\n <div>\n <dt class=\"text-sm font-medium text-gray-500\">User ID</dt>\n <dd class=\"mt-1 text-sm text-gray-900 font-mono\">${log.userId}</dd>\n </div>\n ` : ''}\n \n ${log.sessionId ? html`\n <div>\n <dt class=\"text-sm font-medium text-gray-500\">Session ID</dt>\n <dd class=\"mt-1 text-sm text-gray-900 font-mono\">${log.sessionId}</dd>\n </div>\n ` : ''}\n \n ${log.requestId ? html`\n <div>\n <dt class=\"text-sm font-medium text-gray-500\">Request ID</dt>\n <dd class=\"mt-1 text-sm text-gray-900 font-mono\">${log.requestId}</dd>\n </div>\n ` : ''}\n \n ${log.ipAddress ? html`\n <div>\n <dt class=\"text-sm font-medium text-gray-500\">IP Address</dt>\n <dd class=\"mt-1 text-sm text-gray-900\">${log.ipAddress}</dd>\n </div>\n ` : ''}\n \n ${log.method && log.url ? html`\n <div class=\"sm:col-span-2\">\n <dt class=\"text-sm font-medium text-gray-500\">HTTP Request</dt>\n <dd class=\"mt-1 text-sm text-gray-900\">\n <span class=\"font-medium\">${log.method}</span> ${log.url}\n ${log.statusCode ? html`<span class=\"ml-2 text-gray-500\">(${log.statusCode})</span>` : ''}\n </dd>\n </div>\n ` : ''}\n \n ${log.duration ? html`\n <div>\n <dt class=\"text-sm font-medium text-gray-500\">Duration</dt>\n <dd class=\"mt-1 text-sm text-gray-900\">${log.formattedDuration}</dd>\n </div>\n ` : ''}\n \n ${log.userAgent ? html`\n <div class=\"sm:col-span-2\">\n <dt class=\"text-sm font-medium text-gray-500\">User Agent</dt>\n <dd class=\"mt-1 text-sm text-gray-900 break-all\">${log.userAgent}</dd>\n </div>\n ` : ''}\n </dl>\n </div>\n </div>\n\n <!-- Message -->\n <div class=\"mt-6 bg-white shadow rounded-lg overflow-hidden\">\n <div class=\"px-6 py-4 border-b border-gray-200\">\n <h3 class=\"text-lg font-medium text-gray-900\">Message</h3>\n </div>\n <div class=\"px-6 py-4\">\n <div class=\"text-sm text-gray-900 whitespace-pre-wrap break-words\">\n ${log.message}\n </div>\n </div>\n </div>\n\n <!-- Tags -->\n ${log.tags && log.tags.length > 0 ? html`\n <div class=\"mt-6 bg-white shadow rounded-lg overflow-hidden\">\n <div class=\"px-6 py-4 border-b border-gray-200\">\n <h3 class=\"text-lg font-medium text-gray-900\">Tags</h3>\n </div>\n <div class=\"px-6 py-4\">\n <div class=\"flex flex-wrap gap-2\">\n ${log.tags.map(tag => html`\n <span class=\"inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-gray-100 text-gray-800\">\n ${tag}\n </span>\n `).join('')}\n </div>\n </div>\n </div>\n ` : ''}\n\n <!-- Additional Data -->\n ${log.data ? html`\n <div class=\"mt-6 bg-white shadow rounded-lg overflow-hidden\">\n <div class=\"px-6 py-4 border-b border-gray-200\">\n <h3 class=\"text-lg font-medium text-gray-900\">Additional Data</h3>\n </div>\n <div class=\"px-6 py-4\">\n <pre class=\"text-sm text-gray-900 bg-gray-50 rounded-md p-4 overflow-x-auto\"><code>${JSON.stringify(log.data, null, 2)}</code></pre>\n </div>\n </div>\n ` : ''}\n\n <!-- Stack Trace -->\n ${log.stackTrace ? html`\n <div class=\"mt-6 bg-white shadow rounded-lg overflow-hidden\">\n <div class=\"px-6 py-4 border-b border-gray-200\">\n <h3 class=\"text-lg font-medium text-gray-900\">Stack Trace</h3>\n </div>\n <div class=\"px-6 py-4\">\n <pre class=\"text-sm text-gray-900 bg-gray-50 rounded-md p-4 overflow-x-auto whitespace-pre-wrap\"><code>${log.stackTrace}</code></pre>\n </div>\n </div>\n ` : ''}\n\n <!-- Actions -->\n <div class=\"mt-6 flex justify-between\">\n <a\n href=\"/admin/logs\"\n class=\"inline-flex items-center px-4 py-2 border border-gray-300 shadow-sm text-sm font-medium rounded-md text-gray-700 bg-white hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500\"\n >\n ← Back to Logs\n </a>\n \n <div class=\"flex space-x-3\">\n ${log.level === 'error' || log.level === 'fatal' ? html`\n <button\n type=\"button\"\n class=\"inline-flex items-center px-4 py-2 border border-transparent shadow-sm text-sm font-medium rounded-md text-white bg-red-600 hover:bg-red-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500\"\n onclick=\"alert('Error reporting functionality would be implemented here')\"\n >\n Report Issue\n </button>\n ` : ''}\n \n <button\n type=\"button\"\n class=\"inline-flex items-center px-4 py-2 border border-transparent shadow-sm text-sm font-medium rounded-md text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500\"\n onclick=\"navigator.clipboard.writeText(JSON.stringify(${JSON.stringify(log)}, null, 2)).then(() => alert('Log details copied to clipboard'))\"\n >\n Copy Details\n </button>\n </div>\n </div>\n </div>\n `\n\n return adminLayoutV2({\n title: `Log Details - ${log.id}`,\n user,\n content: content as string\n })\n}","import { html } from 'hono/html'\nimport { adminLayoutV2 } from '../layouts/admin-layout-v2.template'\nimport type { LogConfig } from '../../db/schema'\n\ninterface BaseUser {\n name: string\n email: string\n role: string\n}\n\nexport interface LogConfigPageData {\n configs: LogConfig[]\n user?: BaseUser\n}\n\nexport function renderLogConfigPage(data: LogConfigPageData) {\n const { configs, user } = data\n\n const content = html`\n <div class=\"px-4 sm:px-6 lg:px-8\">\n <div class=\"sm:flex sm:items-center\">\n <div class=\"sm:flex-auto\">\n <nav class=\"mb-4\">\n <a href=\"/admin/logs\" class=\"text-indigo-600 hover:text-indigo-900\">\n ← Back to Logs\n </a>\n </nav>\n <h1 class=\"text-2xl font-semibold text-gray-900\">Log Configuration</h1>\n <p class=\"mt-2 text-sm text-gray-700\">\n Configure logging settings for different categories and manage log retention policies.\n </p>\n </div>\n <div class=\"mt-4 sm:mt-0 sm:ml-16 sm:flex-none\">\n <button\n type=\"button\"\n hx-post=\"/admin/logs/cleanup\"\n hx-confirm=\"Are you sure you want to run log cleanup? This will permanently delete old logs based on retention policies.\"\n hx-target=\"#cleanup-result\"\n class=\"inline-flex items-center justify-center rounded-md border border-transparent bg-red-600 px-4 py-2 text-sm font-medium text-white shadow-sm hover:bg-red-700 focus:outline-none focus:ring-2 focus:ring-red-500 focus:ring-offset-2\"\n >\n Run Cleanup\n </button>\n </div>\n </div>\n\n <div id=\"cleanup-result\" class=\"mt-4\"></div>\n\n <!-- Log Levels Reference -->\n <div class=\"mt-6 bg-white shadow rounded-lg\">\n <div class=\"px-6 py-4 border-b border-gray-200\">\n <h2 class=\"text-lg font-medium text-gray-900\">Log Levels Reference</h2>\n </div>\n <div class=\"px-6 py-4\">\n <div class=\"grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-5\">\n <div class=\"text-center\">\n <span class=\"px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-gray-100 text-gray-800\">\n debug\n </span>\n <p class=\"mt-2 text-xs text-gray-500\">Detailed diagnostic information</p>\n </div>\n <div class=\"text-center\">\n <span class=\"px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-blue-100 text-blue-800\">\n info\n </span>\n <p class=\"mt-2 text-xs text-gray-500\">General information messages</p>\n </div>\n <div class=\"text-center\">\n <span class=\"px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-yellow-100 text-yellow-800\">\n warn\n </span>\n <p class=\"mt-2 text-xs text-gray-500\">Warning conditions</p>\n </div>\n <div class=\"text-center\">\n <span class=\"px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-red-100 text-red-800\">\n error\n </span>\n <p class=\"mt-2 text-xs text-gray-500\">Error conditions</p>\n </div>\n <div class=\"text-center\">\n <span class=\"px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-purple-100 text-purple-800\">\n fatal\n </span>\n <p class=\"mt-2 text-xs text-gray-500\">Critical system errors</p>\n </div>\n </div>\n </div>\n </div>\n\n <!-- Configuration Cards -->\n <div class=\"mt-8 grid grid-cols-1 gap-6 sm:grid-cols-2 lg:grid-cols-3\">\n ${configs.map(config => html`\n <div class=\"bg-white shadow rounded-lg overflow-hidden\">\n <div class=\"px-6 py-4 border-b border-gray-200\">\n <div class=\"flex items-center justify-between\">\n <h3 class=\"text-lg font-medium text-gray-900 capitalize\">${config.category}</h3>\n <div class=\"flex items-center\">\n ${config.enabled ? html`\n <span class=\"px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-green-100 text-green-800\">\n Enabled\n </span>\n ` : html`\n <span class=\"px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-red-100 text-red-800\">\n Disabled\n </span>\n `}\n </div>\n </div>\n </div>\n \n <form hx-post=\"/admin/logs/config/${config.category}\" hx-target=\"#config-result-${config.category}\">\n <div class=\"px-6 py-4 space-y-4\">\n <div class=\"flex gap-3\">\n <div class=\"flex h-6 shrink-0 items-center\">\n <div class=\"group grid size-4 grid-cols-1\">\n <input\n id=\"enabled-${config.category}\"\n name=\"enabled\"\n type=\"checkbox\"\n ${config.enabled ? 'checked' : ''}\n class=\"col-start-1 row-start-1 appearance-none rounded border border-zinc-950/10 dark:border-white/10 bg-white dark:bg-white/5 checked:border-indigo-500 checked:bg-indigo-500 indeterminate:border-indigo-500 indeterminate:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-500 disabled:border-zinc-950/5 dark:disabled:border-white/5 disabled:bg-zinc-950/10 dark:disabled:bg-white/10 disabled:checked:bg-zinc-950/10 dark:disabled:checked:bg-white/10 forced-colors:appearance-auto\"\n />\n <svg viewBox=\"0 0 14 14\" fill=\"none\" class=\"pointer-events-none col-start-1 row-start-1 size-3.5 self-center justify-self-center stroke-white group-has-[:disabled]:stroke-zinc-950/25 dark:group-has-[:disabled]:stroke-white/25\">\n <path d=\"M3 8L6 11L11 3.5\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"opacity-0 group-has-[:checked]:opacity-100\" />\n <path d=\"M3 7H11\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"opacity-0 group-has-[:indeterminate]:opacity-100\" />\n </svg>\n </div>\n </div>\n <div class=\"text-sm/6\">\n <label for=\"enabled-${config.category}\" class=\"font-medium text-zinc-950 dark:text-white\">\n Enable logging for this category\n </label>\n </div>\n </div>\n \n <div>\n <label for=\"level-${config.category}\" class=\"block text-sm font-medium text-gray-700\">\n Minimum Log Level\n </label>\n <select\n id=\"level-${config.category}\"\n name=\"level\"\n class=\"mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm\"\n >\n <option value=\"debug\" ${config.level === 'debug' ? 'selected' : ''}>Debug</option>\n <option value=\"info\" ${config.level === 'info' ? 'selected' : ''}>Info</option>\n <option value=\"warn\" ${config.level === 'warn' ? 'selected' : ''}>Warning</option>\n <option value=\"error\" ${config.level === 'error' ? 'selected' : ''}>Error</option>\n <option value=\"fatal\" ${config.level === 'fatal' ? 'selected' : ''}>Fatal</option>\n </select>\n <p class=\"mt-1 text-sm text-gray-500\">Only logs at this level or higher will be stored</p>\n </div>\n \n <div>\n <label for=\"retention-${config.category}\" class=\"block text-sm font-medium text-gray-700\">\n Retention Period (days)\n </label>\n <input\n type=\"number\"\n id=\"retention-${config.category}\"\n name=\"retention\"\n value=\"${config.retention}\"\n min=\"1\"\n max=\"365\"\n class=\"mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm\"\n />\n <p class=\"mt-1 text-sm text-gray-500\">Logs older than this will be deleted</p>\n </div>\n \n <div>\n <label for=\"max_size-${config.category}\" class=\"block text-sm font-medium text-gray-700\">\n Maximum Log Count\n </label>\n <input\n type=\"number\"\n id=\"max_size-${config.category}\"\n name=\"max_size\"\n value=\"${config.maxSize || ''}\"\n min=\"100\"\n max=\"100000\"\n class=\"mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm\"\n />\n <p class=\"mt-1 text-sm text-gray-500\">Maximum number of logs to keep for this category</p>\n </div>\n </div>\n \n <div class=\"px-6 py-4 bg-gray-50 border-t border-gray-200\">\n <div id=\"config-result-${config.category}\" class=\"mb-4\"></div>\n <button\n type=\"submit\"\n class=\"w-full inline-flex justify-center items-center px-4 py-2 border border-transparent shadow-sm text-sm font-medium rounded-md text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500\"\n >\n Update Configuration\n </button>\n </div>\n </form>\n \n <div class=\"px-6 py-3 bg-gray-50 border-t border-gray-200\">\n <div class=\"text-xs text-gray-500\">\n <div>Created: ${new Date(config.createdAt).toLocaleDateString()}</div>\n <div>Updated: ${new Date(config.updatedAt).toLocaleDateString()}</div>\n </div>\n </div>\n </div>\n `).join('')}\n </div>\n\n <!-- Global Settings -->\n <div class=\"mt-8 bg-white shadow rounded-lg\">\n <div class=\"px-6 py-4 border-b border-gray-200\">\n <h2 class=\"text-lg font-medium text-gray-900\">Global Log Settings</h2>\n </div>\n <div class=\"px-6 py-4\">\n <div class=\"space-y-6\">\n <div>\n <h3 class=\"text-base font-medium text-gray-900\">Storage Information</h3>\n <div class=\"mt-2 grid grid-cols-1 gap-4 sm:grid-cols-3\">\n <div class=\"bg-gray-50 rounded-lg p-4\">\n <div class=\"text-2xl font-bold text-gray-900\">-</div>\n <div class=\"text-sm text-gray-500\">Total Log Entries</div>\n </div>\n <div class=\"bg-gray-50 rounded-lg p-4\">\n <div class=\"text-2xl font-bold text-gray-900\">-</div>\n <div class=\"text-sm text-gray-500\">Storage Used</div>\n </div>\n <div class=\"bg-gray-50 rounded-lg p-4\">\n <div class=\"text-2xl font-bold text-gray-900\">-</div>\n <div class=\"text-sm text-gray-500\">Oldest Log</div>\n </div>\n </div>\n </div>\n \n <div>\n <h3 class=\"text-base font-medium text-gray-900\">Log Categories</h3>\n <div class=\"mt-2 text-sm text-gray-600\">\n <ul class=\"list-disc list-inside space-y-1\">\n <li><strong>auth</strong> - Authentication and authorization events</li>\n <li><strong>api</strong> - API requests and responses</li>\n <li><strong>workflow</strong> - Content workflow state changes</li>\n <li><strong>plugin</strong> - Plugin-related activities</li>\n <li><strong>media</strong> - File upload and media operations</li>\n <li><strong>system</strong> - General system events</li>\n <li><strong>security</strong> - Security-related events and alerts</li>\n <li><strong>error</strong> - General error conditions</li>\n </ul>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n\n <script src=\"https://unpkg.com/htmx.org@1.9.6\"></script>\n `\n\n return adminLayoutV2({\n title: 'Log Configuration',\n user,\n content: content as string\n })\n}","import { Hono } from 'hono'\nimport { html } from 'hono/html'\nimport type { D1Database, KVNamespace } from '@cloudflare/workers-types'\nimport { requireAuth } from '../middleware'\nimport { getLogger, type LogLevel, type LogCategory, type LogFilter } from '../services'\nimport { renderLogsListPage, type LogsListPageData } from '../templates/pages/admin-logs-list.template'\nimport { renderLogDetailsPage, type LogDetailsPageData } from '../templates/pages/admin-log-details.template'\nimport { renderLogConfigPage, type LogConfigPageData } from '../templates/pages/admin-log-config.template'\nimport type { Bindings, Variables } from '../app'\n\nconst adminLogsRoutes = new Hono<{ Bindings: Bindings; Variables: Variables }>()\n\n// Apply authentication middleware\nadminLogsRoutes.use('*', requireAuth())\n\n// Main logs listing page\nadminLogsRoutes.get('/', async (c) => {\n try {\n const user = c.get('user')\n const logger = getLogger(c.env.DB)\n \n // Use Hono's built-in query method instead of parsing URL\n const query = c.req.query()\n \n // Parse query parameters\n const page = parseInt(query.page || '1')\n const limit = parseInt(query.limit || '50')\n const level = query.level\n const category = query.category\n const search = query.search\n const startDate = query.start_date\n const endDate = query.end_date\n const source = query.source\n \n // Build filter\n const filter: LogFilter = {\n limit,\n offset: (page - 1) * limit,\n sortBy: 'created_at',\n sortOrder: 'desc'\n }\n \n if (level) {\n filter.level = level.split(',') as LogLevel[]\n }\n \n if (category) {\n filter.category = category.split(',') as LogCategory[]\n }\n \n if (search) {\n filter.search = search\n }\n \n if (startDate) {\n filter.startDate = new Date(startDate)\n }\n \n if (endDate) {\n filter.endDate = new Date(endDate)\n }\n \n if (source) {\n filter.source = source\n }\n \n // Get logs and total count\n const { logs, total } = await logger.getLogs(filter)\n \n // Format logs for display\n const formattedLogs = logs.map(log => ({\n ...log,\n data: log.data ? JSON.parse(log.data) : null,\n tags: log.tags ? JSON.parse(log.tags) : [],\n formattedDate: new Date(log.createdAt).toLocaleString(),\n formattedDuration: log.duration ? `${log.duration}ms` : null,\n levelClass: getLevelClass(log.level),\n categoryClass: getCategoryClass(log.category)\n }))\n \n const totalPages = Math.ceil(total / limit)\n \n const pageData: LogsListPageData = {\n logs: formattedLogs,\n pagination: {\n currentPage: page,\n totalPages,\n totalItems: total,\n itemsPerPage: limit,\n startItem: (page - 1) * limit + 1,\n endItem: Math.min(page * limit, total),\n baseUrl: '/admin/logs'\n },\n filters: {\n level: level || '',\n category: category || '',\n search: search || '',\n startDate: startDate || '',\n endDate: endDate || '',\n source: source || ''\n },\n user: user ? {\n name: user.email,\n email: user.email,\n role: user.role\n } : undefined\n }\n \n return c.html(renderLogsListPage(pageData))\n } catch (error) {\n console.error('Error fetching logs:', error)\n return c.html(html`<p>Error loading logs: ${error}</p>`)\n }\n})\n\n// Log details page\nadminLogsRoutes.get('/:id', async (c) => {\n try {\n const id = c.req.param('id')\n const user = c.get('user')\n const logger = getLogger(c.env.DB)\n \n // Get single log by ID\n const { logs } = await logger.getLogs({ \n limit: 1, \n offset: 0,\n search: id // Using search to find by ID - this is a simplification\n })\n \n const log = logs.find(l => l.id === id)\n \n if (!log) {\n return c.html(html`<p>Log entry not found</p>`)\n }\n \n const formattedLog = {\n ...log,\n data: log.data ? JSON.parse(log.data) : null,\n tags: log.tags ? JSON.parse(log.tags) : [],\n formattedDate: new Date(log.createdAt).toLocaleString(),\n formattedDuration: log.duration ? `${log.duration}ms` : null,\n levelClass: getLevelClass(log.level),\n categoryClass: getCategoryClass(log.category)\n }\n \n const pageData: LogDetailsPageData = {\n log: formattedLog,\n user: user ? {\n name: user.email,\n email: user.email,\n role: user.role\n } : undefined\n }\n \n return c.html(renderLogDetailsPage(pageData))\n } catch (error) {\n console.error('Error fetching log details:', error)\n return c.html(html`<p>Error loading log details: ${error}</p>`)\n }\n})\n\n// Log configuration page\nadminLogsRoutes.get('/config', async (c) => {\n try {\n const user = c.get('user')\n const logger = getLogger(c.env.DB)\n \n // Get all log configurations\n const configs = await logger.getAllConfigs()\n \n const pageData: LogConfigPageData = {\n configs,\n user: user ? {\n name: user.email,\n email: user.email,\n role: user.role\n } : undefined\n }\n \n return c.html(renderLogConfigPage(pageData))\n } catch (error) {\n console.error('Error fetching log config:', error)\n return c.html(html`<p>Error loading log configuration: ${error}</p>`)\n }\n})\n\n// Update log configuration\nadminLogsRoutes.post('/config/:category', async (c) => {\n try {\n const category = c.req.param('category') as LogCategory\n const formData = await c.req.formData()\n \n const enabled = formData.get('enabled') === 'on'\n const level = formData.get('level') as string\n const retention = parseInt(formData.get('retention') as string)\n const maxSize = parseInt(formData.get('max_size') as string)\n \n const logger = getLogger(c.env.DB)\n await logger.updateConfig(category, {\n enabled,\n level,\n retention,\n maxSize\n })\n \n return c.html(html`\n <div class=\"bg-green-100 border border-green-400 text-green-700 px-4 py-3 rounded\">\n Configuration updated successfully!\n </div>\n `)\n } catch (error) {\n console.error('Error updating log config:', error)\n return c.html(html`\n <div class=\"bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded\">\n Failed to update configuration. Please try again.\n </div>\n `)\n }\n})\n\n// Export logs\nadminLogsRoutes.get('/export', async (c) => {\n try {\n const query = c.req.query()\n const format = query.format || 'csv'\n const level = query.level\n const category = query.category\n const startDate = query.start_date\n const endDate = query.end_date\n \n const logger = getLogger(c.env.DB)\n \n // Build filter for export\n const filter: LogFilter = {\n limit: 10000, // Export up to 10k logs\n offset: 0,\n sortBy: 'created_at',\n sortOrder: 'desc'\n }\n \n if (level) {\n filter.level = level.split(',') as LogLevel[]\n }\n \n if (category) {\n filter.category = category.split(',') as LogCategory[]\n }\n \n if (startDate) {\n filter.startDate = new Date(startDate)\n }\n \n if (endDate) {\n filter.endDate = new Date(endDate)\n }\n \n const { logs } = await logger.getLogs(filter)\n \n if (format === 'json') {\n return c.json(logs, 200, {\n 'Content-Disposition': 'attachment; filename=\"logs-export.json\"'\n })\n } else {\n // Default to CSV\n const headers = [\n 'ID', 'Level', 'Category', 'Message', 'Source', 'User ID', \n 'IP Address', 'Method', 'URL', 'Status Code', 'Duration', \n 'Created At'\n ]\n const csvRows = [headers.join(',')]\n \n logs.forEach(log => {\n const row = [\n log.id,\n log.level,\n log.category,\n `\"${log.message.replace(/\"/g, '\"\"')}\"`, // Escape quotes\n log.source || '',\n log.userId || '',\n log.ipAddress || '',\n log.method || '',\n log.url || '',\n log.statusCode || '',\n log.duration || '',\n new Date(log.createdAt).toISOString()\n ]\n csvRows.push(row.join(','))\n })\n \n const csv = csvRows.join('\\n')\n \n return new Response(csv, {\n headers: {\n 'Content-Type': 'text/csv',\n 'Content-Disposition': 'attachment; filename=\"logs-export.csv\"'\n }\n })\n }\n } catch (error) {\n console.error('Error exporting logs:', error)\n return c.json({ error: 'Failed to export logs' }, 500)\n }\n})\n\n// Clean up old logs\nadminLogsRoutes.post('/cleanup', async (c) => {\n try {\n const user = c.get('user')\n \n // Only allow admin users to run cleanup\n if (!user || user.role !== 'admin') {\n return c.json({ \n success: false, \n error: 'Unauthorized. Admin access required.' \n }, 403)\n }\n \n const logger = getLogger(c.env.DB)\n await logger.cleanupByRetention()\n \n return c.html(html`\n <div class=\"bg-green-100 border border-green-400 text-green-700 px-4 py-3 rounded\">\n Log cleanup completed successfully!\n </div>\n `)\n } catch (error) {\n console.error('Error cleaning up logs:', error)\n return c.html(html`\n <div class=\"bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded\">\n Failed to clean up logs. Please try again.\n </div>\n `)\n }\n})\n\n// Search logs (HTMX endpoint)\nadminLogsRoutes.post('/search', async (c) => {\n try {\n const formData = await c.req.formData()\n const search = formData.get('search') as string\n const level = formData.get('level') as string\n const category = formData.get('category') as string\n \n const logger = getLogger(c.env.DB)\n \n const filter: LogFilter = {\n limit: 20,\n offset: 0,\n sortBy: 'created_at',\n sortOrder: 'desc'\n }\n \n if (search) filter.search = search\n if (level) filter.level = [level] as LogLevel[]\n if (category) filter.category = [category] as LogCategory[]\n \n const { logs } = await logger.getLogs(filter)\n \n // Return just the logs table rows for HTMX\n const rows = logs.map(log => {\n const formattedLog = {\n ...log,\n formattedDate: new Date(log.createdAt).toLocaleString(),\n levelClass: getLevelClass(log.level),\n categoryClass: getCategoryClass(log.category)\n }\n\n return `\n <tr class=\"hover:bg-gray-50\">\n <td class=\"px-6 py-4 whitespace-nowrap\">\n <span class=\"px-2 inline-flex text-xs leading-5 font-semibold rounded-full ${formattedLog.levelClass}\">\n ${formattedLog.level}\n </span>\n </td>\n <td class=\"px-6 py-4 whitespace-nowrap\">\n <span class=\"px-2 inline-flex text-xs leading-5 font-semibold rounded-full ${formattedLog.categoryClass}\">\n ${formattedLog.category}\n </span>\n </td>\n <td class=\"px-6 py-4\">\n <div class=\"text-sm text-gray-900 max-w-md truncate\">${formattedLog.message}</div>\n </td>\n <td class=\"px-6 py-4 whitespace-nowrap text-sm text-gray-500\">${formattedLog.source || '-'}</td>\n <td class=\"px-6 py-4 whitespace-nowrap text-sm text-gray-500\">${formattedLog.formattedDate}</td>\n <td class=\"px-6 py-4 whitespace-nowrap text-right text-sm font-medium\">\n <a href=\"/admin/logs/${formattedLog.id}\" class=\"text-indigo-600 hover:text-indigo-900\">View</a>\n </td>\n </tr>\n `\n }).join('')\n\n return c.html(rows)\n } catch (error) {\n console.error('Error searching logs:', error)\n return c.html(html`<tr><td colspan=\"6\" class=\"px-6 py-4 text-center text-red-500\">Error searching logs</td></tr>`)\n }\n})\n\n// Helper functions\nfunction getLevelClass(level: string): string {\n switch (level) {\n case 'debug': return 'bg-gray-100 text-gray-800'\n case 'info': return 'bg-blue-100 text-blue-800'\n case 'warn': return 'bg-yellow-100 text-yellow-800'\n case 'error': return 'bg-red-100 text-red-800'\n case 'fatal': return 'bg-purple-100 text-purple-800'\n default: return 'bg-gray-100 text-gray-800'\n }\n}\n\nfunction getCategoryClass(category: string): string {\n switch (category) {\n case 'auth': return 'bg-green-100 text-green-800'\n case 'api': return 'bg-blue-100 text-blue-800'\n case 'workflow': return 'bg-purple-100 text-purple-800'\n case 'plugin': return 'bg-indigo-100 text-indigo-800'\n case 'media': return 'bg-pink-100 text-pink-800'\n case 'system': return 'bg-gray-100 text-gray-800'\n case 'security': return 'bg-red-100 text-red-800'\n case 'error': return 'bg-red-100 text-red-800'\n default: return 'bg-gray-100 text-gray-800'\n }\n}\n\nexport { adminLogsRoutes }","import { Hono } from 'hono'\nimport { renderDesignPage, DesignPageData } from '../templates/pages/admin-design.template'\n\ntype Bindings = {\n DB: D1Database\n KV: KVNamespace\n}\n\ntype Variables = {\n user: {\n userId: string\n email: string\n role: string\n }\n}\n\nexport const adminDesignRoutes = new Hono<{ Bindings: Bindings; Variables: Variables }>()\n\nadminDesignRoutes.get('/', (c) => {\n const user = c.get('user')\n \n const pageData: DesignPageData = {\n user: user ? {\n name: user.email,\n email: user.email,\n role: user.role\n } : undefined\n }\n \n return c.html(renderDesignPage(pageData))\n})","import { Hono } from 'hono'\nimport { renderCheckboxPage, CheckboxPageData } from '../templates/pages/admin-checkboxes.template'\n\ntype Bindings = {\n DB: D1Database\n KV: KVNamespace\n}\n\ntype Variables = {\n user: {\n userId: string\n email: string\n role: string\n }\n}\n\nexport const adminCheckboxRoutes = new Hono<{ Bindings: Bindings; Variables: Variables }>()\n\nadminCheckboxRoutes.get('/', (c) => {\n const user = c.get('user')\n\n const pageData: CheckboxPageData = {\n user: user ? {\n name: user.email,\n email: user.email,\n role: user.role\n } : undefined\n }\n\n return c.html(renderCheckboxPage(pageData))\n})\n","import { renderAdminLayout, AdminLayoutData } from '../layouts/admin-layout-v2.template'\nimport { renderAlert } from '../alert.template'\n\ninterface Testimonial {\n id?: number\n authorName: string\n authorTitle?: string\n authorCompany?: string\n testimonialText: string\n rating?: number\n isPublished: boolean\n sortOrder: number\n}\n\ninterface TestimonialsFormData {\n testimonial?: Testimonial\n isEdit: boolean\n errors?: Record<string, string[]>\n user?: { name: string; email: string; role: string }\n message?: string\n messageType?: 'success' | 'error' | 'warning' | 'info'\n}\n\nexport function renderTestimonialsForm(data: TestimonialsFormData): string {\n const { testimonial, isEdit, errors, message, messageType } = data\n const pageTitle = isEdit ? 'Edit Testimonial' : 'New Testimonial'\n\n const pageContent = `\n <div class=\"w-full px-4 sm:px-6 lg:px-8 py-6 space-y-6\">\n <!-- Header -->\n <div class=\"flex flex-col sm:flex-row sm:items-center sm:justify-between mb-6\">\n <div>\n <h1 class=\"text-2xl font-semibold text-white\">${pageTitle}</h1>\n <p class=\"mt-2 text-sm text-gray-300\">\n ${isEdit ? 'Update the testimonial details below' : 'Create a new customer testimonial'}\n </p>\n </div>\n <div class=\"mt-4 sm:mt-0 sm:ml-16 sm:flex-none\">\n <a href=\"/admin/testimonials\"\n class=\"inline-flex items-center justify-center rounded-xl backdrop-blur-sm bg-white/10 px-4 py-2 text-sm font-semibold text-white border border-white/20 hover:bg-white/20 transition-all\">\n <svg class=\"-ml-0.5 mr-1.5 h-5 w-5\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M10 19l-7-7m0 0l7-7m-7 7h18\" />\n </svg>\n Back to List\n </a>\n </div>\n </div>\n\n ${message ? renderAlert({ type: messageType || 'info', message, dismissible: true }) : ''}\n\n <!-- Form -->\n <div class=\"backdrop-blur-xl bg-white/10 rounded-xl border border-white/20 shadow-2xl\">\n <form ${isEdit ? `hx-put=\"/admin/testimonials/${testimonial?.id}\"` : 'hx-post=\"/admin/testimonials\"'}\n hx-target=\"body\"\n hx-swap=\"outerHTML\"\n class=\"space-y-6 p-6\">\n\n <!-- Author Information Section -->\n <div>\n <h2 class=\"text-lg font-medium text-white mb-4\">Author Information</h2>\n\n <!-- Author Name -->\n <div class=\"mb-4\">\n <label for=\"authorName\" class=\"block text-sm font-medium text-white\">\n Author Name <span class=\"text-red-400\">*</span>\n </label>\n <div class=\"mt-1\">\n <input type=\"text\"\n name=\"authorName\"\n id=\"authorName\"\n value=\"${testimonial?.authorName || ''}\"\n required\n maxlength=\"100\"\n class=\"block w-full rounded-md border-0 bg-gray-700 py-1.5 text-gray-100 shadow-sm ring-1 ring-inset ring-gray-600 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-blue-600 sm:text-sm sm:leading-6\"\n placeholder=\"John Doe\">\n </div>\n ${errors?.authorName ? `\n <div class=\"mt-1\">\n ${errors.authorName.map(error => `\n <p class=\"text-sm text-red-400\">${escapeHtml(error)}</p>\n `).join('')}\n </div>\n ` : ''}\n </div>\n\n <div class=\"grid grid-cols-1 md:grid-cols-2 gap-6\">\n <!-- Author Title -->\n <div>\n <label for=\"authorTitle\" class=\"block text-sm font-medium text-white\">Title/Position</label>\n <div class=\"mt-1\">\n <input type=\"text\"\n name=\"authorTitle\"\n id=\"authorTitle\"\n value=\"${testimonial?.authorTitle || ''}\"\n maxlength=\"100\"\n class=\"block w-full rounded-md border-0 bg-gray-700 py-1.5 text-gray-100 shadow-sm ring-1 ring-inset ring-gray-600 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-blue-600 sm:text-sm sm:leading-6\"\n placeholder=\"CEO\">\n </div>\n ${errors?.authorTitle ? `\n <div class=\"mt-1\">\n ${errors.authorTitle.map(error => `\n <p class=\"text-sm text-red-400\">${escapeHtml(error)}</p>\n `).join('')}\n </div>\n ` : ''}\n </div>\n\n <!-- Author Company -->\n <div>\n <label for=\"authorCompany\" class=\"block text-sm font-medium text-white\">Company</label>\n <div class=\"mt-1\">\n <input type=\"text\"\n name=\"authorCompany\"\n id=\"authorCompany\"\n value=\"${testimonial?.authorCompany || ''}\"\n maxlength=\"100\"\n class=\"block w-full rounded-md border-0 bg-gray-700 py-1.5 text-gray-100 shadow-sm ring-1 ring-inset ring-gray-600 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-blue-600 sm:text-sm sm:leading-6\"\n placeholder=\"Acme Corp\">\n </div>\n ${errors?.authorCompany ? `\n <div class=\"mt-1\">\n ${errors.authorCompany.map(error => `\n <p class=\"text-sm text-red-400\">${escapeHtml(error)}</p>\n `).join('')}\n </div>\n ` : ''}\n </div>\n </div>\n </div>\n\n <!-- Testimonial Content Section -->\n <div>\n <h2 class=\"text-lg font-medium text-white mb-4\">Testimonial</h2>\n\n <!-- Testimonial Text -->\n <div class=\"mb-4\">\n <label for=\"testimonialText\" class=\"block text-sm font-medium text-white\">\n Testimonial <span class=\"text-red-400\">*</span>\n </label>\n <div class=\"mt-1\">\n <textarea name=\"testimonialText\"\n id=\"testimonialText\"\n rows=\"6\"\n required\n maxlength=\"1000\"\n class=\"backdrop-blur-sm bg-white/10 border border-white/20 rounded-xl px-3 py-2 text-white placeholder-gray-300 focus:border-blue-400 focus:outline-none transition-colors w-full\"\n placeholder=\"Enter the customer's testimonial...\">${testimonial?.testimonialText || ''}</textarea>\n <p class=\"mt-1 text-sm text-gray-300\">\n <span id=\"testimonial-count\">0</span>/1000 characters\n </p>\n </div>\n ${errors?.testimonialText ? `\n <div class=\"mt-1\">\n ${errors.testimonialText.map(error => `\n <p class=\"text-sm text-red-400\">${escapeHtml(error)}</p>\n `).join('')}\n </div>\n ` : ''}\n </div>\n\n <!-- Rating -->\n <div>\n <label for=\"rating\" class=\"block text-sm font-medium text-white\">Rating (Optional)</label>\n <div class=\"mt-1\">\n <select name=\"rating\"\n id=\"rating\"\n class=\"block w-full rounded-md border-0 bg-gray-700 py-1.5 text-gray-100 shadow-sm ring-1 ring-inset ring-gray-600 focus:ring-2 focus:ring-inset focus:ring-blue-600 sm:text-sm sm:leading-6\">\n <option value=\"\">No rating</option>\n <option value=\"5\" ${testimonial?.rating === 5 ? 'selected' : ''}>⭐⭐⭐⭐⭐ (5 stars)</option>\n <option value=\"4\" ${testimonial?.rating === 4 ? 'selected' : ''}>⭐⭐⭐⭐ (4 stars)</option>\n <option value=\"3\" ${testimonial?.rating === 3 ? 'selected' : ''}>⭐⭐⭐ (3 stars)</option>\n <option value=\"2\" ${testimonial?.rating === 2 ? 'selected' : ''}>⭐⭐ (2 stars)</option>\n <option value=\"1\" ${testimonial?.rating === 1 ? 'selected' : ''}>⭐ (1 star)</option>\n </select>\n </div>\n ${errors?.rating ? `\n <div class=\"mt-1\">\n ${errors.rating.map(error => `\n <p class=\"text-sm text-red-400\">${escapeHtml(error)}</p>\n `).join('')}\n </div>\n ` : ''}\n </div>\n </div>\n\n <!-- Status and Sort Order Row -->\n <div class=\"grid grid-cols-1 md:grid-cols-2 gap-6\">\n <!-- Published Status -->\n <div>\n <label class=\"block text-sm font-medium text-white\">Status</label>\n <div class=\"mt-2 space-y-2\">\n <div class=\"flex items-center\">\n <input id=\"published\"\n name=\"isPublished\"\n type=\"radio\"\n value=\"true\"\n ${!testimonial || testimonial.isPublished ? 'checked' : ''}\n class=\"h-4 w-4 text-blue-600 focus:ring-blue-600 border-gray-600 bg-gray-700\">\n <label for=\"published\" class=\"ml-2 block text-sm text-white\">\n Published <span class=\"text-gray-300\">(visible to users)</span>\n </label>\n </div>\n <div class=\"flex items-center\">\n <input id=\"draft\"\n name=\"isPublished\"\n type=\"radio\"\n value=\"false\"\n ${testimonial && !testimonial.isPublished ? 'checked' : ''}\n class=\"h-4 w-4 text-blue-600 focus:ring-blue-600 border-gray-600 bg-gray-700\">\n <label for=\"draft\" class=\"ml-2 block text-sm text-white\">\n Draft <span class=\"text-gray-300\">(not visible to users)</span>\n </label>\n </div>\n </div>\n </div>\n\n <!-- Sort Order -->\n <div>\n <label for=\"sortOrder\" class=\"block text-sm font-medium text-white\">Sort Order</label>\n <div class=\"mt-1\">\n <input type=\"number\"\n name=\"sortOrder\"\n id=\"sortOrder\"\n value=\"${testimonial?.sortOrder || 0}\"\n min=\"0\"\n step=\"1\"\n class=\"block w-full rounded-md border-0 bg-gray-700 py-1.5 text-gray-100 shadow-sm ring-1 ring-inset ring-gray-600 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-blue-600 sm:text-sm sm:leading-6\">\n <p class=\"mt-1 text-sm text-gray-300\">Lower numbers appear first (0 = highest priority)</p>\n </div>\n ${errors?.sortOrder ? `\n <div class=\"mt-1\">\n ${errors.sortOrder.map(error => `\n <p class=\"text-sm text-red-400\">${escapeHtml(error)}</p>\n `).join('')}\n </div>\n ` : ''}\n </div>\n </div>\n\n <!-- Form Actions -->\n <div class=\"flex items-center justify-end space-x-3 pt-6 border-t border-white/20\">\n <a href=\"/admin/testimonials\"\n class=\"inline-flex items-center justify-center rounded-xl backdrop-blur-sm bg-white/10 px-4 py-2 text-sm font-semibold text-white border border-white/20 hover:bg-white/20 transition-all\">\n Cancel\n </a>\n <button type=\"submit\"\n class=\"inline-flex items-center justify-center rounded-xl backdrop-blur-sm bg-blue-500/80 px-4 py-2 text-sm font-semibold text-white border border-white/20 hover:bg-blue-500 transition-all\">\n <svg class=\"-ml-0.5 mr-1.5 h-5 w-5\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M5 13l4 4L19 7\" />\n </svg>\n ${isEdit ? 'Update Testimonial' : 'Create Testimonial'}\n </button>\n </div>\n </form>\n </div>\n </div>\n\n <script>\n // Character count for testimonial\n const testimonialTextarea = document.getElementById('testimonialText');\n const testimonialCount = document.getElementById('testimonial-count');\n\n function updateTestimonialCount() {\n testimonialCount.textContent = testimonialTextarea.value.length;\n }\n\n testimonialTextarea.addEventListener('input', updateTestimonialCount);\n updateTestimonialCount(); // Initial count\n </script>\n `\n\n const layoutData: AdminLayoutData = {\n title: `${pageTitle} - Admin`,\n pageTitle,\n currentPath: isEdit ? `/admin/testimonials/${testimonial?.id}` : '/admin/testimonials/new',\n user: data.user,\n content: pageContent\n }\n\n return renderAdminLayout(layoutData)\n}\n\nfunction escapeHtml(unsafe: string): string {\n return unsafe\n .replace(/&/g, \"&\")\n .replace(/</g, \"<\")\n .replace(/>/g, \">\")\n .replace(/\"/g, \""\")\n .replace(/'/g, \"'\")\n}\n","import { Hono } from 'hono'\nimport { z } from 'zod'\nimport { renderTestimonialsList } from '../templates/pages/admin-testimonials-list.template'\nimport { renderTestimonialsForm } from '../templates/pages/admin-testimonials-form.template'\n\ntype Bindings = {\n DB: D1Database\n KV: KVNamespace\n}\n\ntype Variables = {\n user?: {\n userId: string\n email: string\n role: string\n exp: number\n iat: number\n }\n}\n\nconst testimonialSchema = z.object({\n authorName: z.string().min(1, 'Author name is required').max(100, 'Author name must be under 100 characters'),\n authorTitle: z.string().optional(),\n authorCompany: z.string().optional(),\n testimonialText: z.string().min(1, 'Testimonial is required').max(1000, 'Testimonial must be under 1000 characters'),\n rating: z.string().transform(val => val ? parseInt(val, 10) : undefined).pipe(z.number().min(1).max(5).optional()),\n isPublished: z.string().transform(val => val === 'true'),\n sortOrder: z.string().transform(val => parseInt(val, 10)).pipe(z.number().min(0))\n})\n\nconst adminTestimonialsRoutes = new Hono<{ Bindings: Bindings; Variables: Variables }>()\n\nadminTestimonialsRoutes.get('/', async (c) => {\n try {\n const user = c.get('user')\n const { published, minRating, search, page = '1' } = c.req.query()\n const currentPage = parseInt(page, 10) || 1\n const limit = 20\n const offset = (currentPage - 1) * limit\n\n const db = (c as any).env?.DB\n if (!db) {\n return c.html(renderTestimonialsList({\n testimonials: [],\n totalCount: 0,\n currentPage: 1,\n totalPages: 1,\n user: user ? {\n name: user.email,\n email: user.email,\n role: user.role\n } : undefined,\n message: 'Database not available',\n messageType: 'error'\n }))\n }\n\n let whereClause = 'WHERE 1=1'\n const params: any[] = []\n\n if (published !== undefined) {\n whereClause += ' AND isPublished = ?'\n params.push(published === 'true' ? 1 : 0)\n }\n\n if (minRating) {\n whereClause += ' AND rating >= ?'\n params.push(parseInt(minRating, 10))\n }\n\n if (search) {\n whereClause += ' AND (author_name LIKE ? OR testimonial_text LIKE ? OR author_company LIKE ?)'\n const searchTerm = `%${search}%`\n params.push(searchTerm, searchTerm, searchTerm)\n }\n\n const countQuery = `SELECT COUNT(*) as count FROM testimonials ${whereClause}`\n const { results: countResults } = await db.prepare(countQuery).bind(...params).all()\n const totalCount = countResults?.[0]?.count || 0\n\n const dataQuery = `\n SELECT * FROM testimonials\n ${whereClause}\n ORDER BY sortOrder ASC, created_at DESC\n LIMIT ? OFFSET ?\n `\n const { results: testimonials } = await db.prepare(dataQuery).bind(...params, limit, offset).all()\n\n const totalPages = Math.ceil(totalCount / limit)\n\n return c.html(renderTestimonialsList({\n testimonials: testimonials || [],\n totalCount,\n currentPage,\n totalPages,\n user: user ? {\n name: user.email,\n email: user.email,\n role: user.role\n } : undefined\n }))\n } catch (error) {\n console.error('Error fetching testimonials:', error)\n const user = c.get('user')\n return c.html(renderTestimonialsList({\n testimonials: [],\n totalCount: 0,\n currentPage: 1,\n totalPages: 1,\n user: user ? {\n name: user.email,\n email: user.email,\n role: user.role\n } : undefined,\n message: 'Failed to load testimonials',\n messageType: 'error'\n }))\n }\n})\n\nadminTestimonialsRoutes.get('/new', async (c) => {\n const user = c.get('user')\n return c.html(renderTestimonialsForm({\n isEdit: false,\n user: user ? {\n name: user.email,\n email: user.email,\n role: user.role\n } : undefined\n }))\n})\n\nadminTestimonialsRoutes.post('/', async (c) => {\n try {\n const formData = await c.req.formData()\n const data = Object.fromEntries(formData.entries())\n\n const validatedData = testimonialSchema.parse(data)\n const user = c.get('user')\n const db = (c as any).env?.DB\n\n if (!db) {\n return c.html(renderTestimonialsForm({\n isEdit: false,\n user: user ? {\n name: user.email,\n email: user.email,\n role: user.role\n } : undefined,\n message: 'Database not available',\n messageType: 'error'\n }))\n }\n\n const { results } = await db.prepare(`\n INSERT INTO testimonials (author_name, author_title, author_company, testimonial_text, rating, isPublished, sortOrder)\n VALUES (?, ?, ?, ?, ?, ?, ?)\n RETURNING *\n `).bind(\n validatedData.authorName,\n validatedData.authorTitle || null,\n validatedData.authorCompany || null,\n validatedData.testimonialText,\n validatedData.rating || null,\n validatedData.isPublished ? 1 : 0,\n validatedData.sortOrder\n ).all()\n\n if (results && results.length > 0) {\n return c.redirect('/admin/testimonials?message=Testimonial created successfully')\n } else {\n return c.html(renderTestimonialsForm({\n isEdit: false,\n user: user ? {\n name: user.email,\n email: user.email,\n role: user.role\n } : undefined,\n message: 'Failed to create testimonial',\n messageType: 'error'\n }))\n }\n } catch (error) {\n console.error('Error creating testimonial:', error)\n const user = c.get('user')\n\n if (error instanceof z.ZodError) {\n const errors: Record<string, string[]> = {}\n error.issues.forEach(err => {\n const field = err.path[0] as string\n if (!errors[field]) errors[field] = []\n errors[field].push(err.message)\n })\n\n return c.html(renderTestimonialsForm({\n isEdit: false,\n user: user ? {\n name: user.email,\n email: user.email,\n role: user.role\n } : undefined,\n errors,\n message: 'Please correct the errors below',\n messageType: 'error'\n }))\n }\n\n return c.html(renderTestimonialsForm({\n isEdit: false,\n user: user ? {\n name: user.email,\n email: user.email,\n role: user.role\n } : undefined,\n message: 'Failed to create testimonial',\n messageType: 'error'\n }))\n }\n})\n\nadminTestimonialsRoutes.get('/:id', async (c) => {\n try {\n const id = parseInt(c.req.param('id'))\n const user = c.get('user')\n const db = (c as any).env?.DB\n\n if (!db) {\n return c.html(renderTestimonialsForm({\n isEdit: true,\n user: user ? {\n name: user.email,\n email: user.email,\n role: user.role\n } : undefined,\n message: 'Database not available',\n messageType: 'error'\n }))\n }\n\n const { results } = await db.prepare('SELECT * FROM testimonials WHERE id = ?').bind(id).all()\n\n if (!results || results.length === 0) {\n return c.redirect('/admin/testimonials?message=Testimonial not found&type=error')\n }\n\n const testimonial = results[0] as any\n\n return c.html(renderTestimonialsForm({\n testimonial: {\n id: testimonial.id,\n authorName: testimonial.author_name,\n authorTitle: testimonial.author_title,\n authorCompany: testimonial.author_company,\n testimonialText: testimonial.testimonial_text,\n rating: testimonial.rating,\n isPublished: Boolean(testimonial.isPublished),\n sortOrder: testimonial.sortOrder\n },\n isEdit: true,\n user: user ? {\n name: user.email,\n email: user.email,\n role: user.role\n } : undefined\n }))\n } catch (error) {\n console.error('Error fetching testimonial:', error)\n const user = c.get('user')\n return c.html(renderTestimonialsForm({\n isEdit: true,\n user: user ? {\n name: user.email,\n email: user.email,\n role: user.role\n } : undefined,\n message: 'Failed to load testimonial',\n messageType: 'error'\n }))\n }\n})\n\nadminTestimonialsRoutes.put('/:id', async (c) => {\n try {\n const id = parseInt(c.req.param('id'))\n const formData = await c.req.formData()\n const data = Object.fromEntries(formData.entries())\n\n const validatedData = testimonialSchema.parse(data)\n const user = c.get('user')\n const db = (c as any).env?.DB\n\n if (!db) {\n return c.html(renderTestimonialsForm({\n isEdit: true,\n user: user ? {\n name: user.email,\n email: user.email,\n role: user.role\n } : undefined,\n message: 'Database not available',\n messageType: 'error'\n }))\n }\n\n const { results } = await db.prepare(`\n UPDATE testimonials\n SET author_name = ?, author_title = ?, author_company = ?, testimonial_text = ?, rating = ?, isPublished = ?, sortOrder = ?\n WHERE id = ?\n RETURNING *\n `).bind(\n validatedData.authorName,\n validatedData.authorTitle || null,\n validatedData.authorCompany || null,\n validatedData.testimonialText,\n validatedData.rating || null,\n validatedData.isPublished ? 1 : 0,\n validatedData.sortOrder,\n id\n ).all()\n\n if (results && results.length > 0) {\n return c.redirect('/admin/testimonials?message=Testimonial updated successfully')\n } else {\n return c.html(renderTestimonialsForm({\n testimonial: {\n id,\n authorName: validatedData.authorName,\n authorTitle: validatedData.authorTitle,\n authorCompany: validatedData.authorCompany,\n testimonialText: validatedData.testimonialText,\n rating: validatedData.rating,\n isPublished: validatedData.isPublished,\n sortOrder: validatedData.sortOrder\n },\n isEdit: true,\n user: user ? {\n name: user.email,\n email: user.email,\n role: user.role\n } : undefined,\n message: 'Testimonial not found',\n messageType: 'error'\n }))\n }\n } catch (error) {\n console.error('Error updating testimonial:', error)\n const user = c.get('user')\n const id = parseInt(c.req.param('id'))\n\n if (error instanceof z.ZodError) {\n const errors: Record<string, string[]> = {}\n error.issues.forEach(err => {\n const field = err.path[0] as string\n if (!errors[field]) errors[field] = []\n errors[field].push(err.message)\n })\n\n return c.html(renderTestimonialsForm({\n testimonial: {\n id,\n authorName: '',\n authorTitle: '',\n authorCompany: '',\n testimonialText: '',\n rating: undefined,\n isPublished: true,\n sortOrder: 0\n },\n isEdit: true,\n user: user ? {\n name: user.email,\n email: user.email,\n role: user.role\n } : undefined,\n errors,\n message: 'Please correct the errors below',\n messageType: 'error'\n }))\n }\n\n return c.html(renderTestimonialsForm({\n testimonial: {\n id,\n authorName: '',\n authorTitle: '',\n authorCompany: '',\n testimonialText: '',\n rating: undefined,\n isPublished: true,\n sortOrder: 0\n },\n isEdit: true,\n user: user ? {\n name: user.email,\n email: user.email,\n role: user.role\n } : undefined,\n message: 'Failed to update testimonial',\n messageType: 'error'\n }))\n }\n})\n\nadminTestimonialsRoutes.delete('/:id', async (c) => {\n try {\n const id = parseInt(c.req.param('id'))\n const db = (c as any).env?.DB\n\n if (!db) {\n return c.json({ error: 'Database not available' }, 500)\n }\n\n const { changes } = await db.prepare('DELETE FROM testimonials WHERE id = ?').bind(id).run()\n\n if (changes === 0) {\n return c.json({ error: 'Testimonial not found' }, 404)\n }\n\n return c.redirect('/admin/testimonials?message=Testimonial deleted successfully')\n } catch (error) {\n console.error('Error deleting testimonial:', error)\n return c.json({ error: 'Failed to delete testimonial' }, 500)\n }\n})\n\nexport default adminTestimonialsRoutes\n","import { renderAdminLayout, AdminLayoutData } from '../layouts/admin-layout-v2.template'\nimport { renderAlert } from '../alert.template'\n\ninterface CodeExample {\n id?: number\n title: string\n description?: string\n code: string\n language: string\n category?: string\n tags?: string\n isPublished: boolean\n sortOrder: number\n}\n\ninterface CodeExamplesFormData {\n codeExample?: CodeExample\n isEdit: boolean\n errors?: Record<string, string[]>\n user?: { name: string; email: string; role: string }\n message?: string\n messageType?: 'success' | 'error' | 'warning' | 'info'\n}\n\nexport function renderCodeExamplesForm(data: CodeExamplesFormData): string {\n const { codeExample, isEdit, errors, message, messageType } = data\n const pageTitle = isEdit ? 'Edit Code Example' : 'New Code Example'\n\n const pageContent = `\n <div class=\"w-full px-4 sm:px-6 lg:px-8 py-6 space-y-6\">\n <!-- Header -->\n <div class=\"flex flex-col sm:flex-row sm:items-center sm:justify-between mb-6\">\n <div>\n <h1 class=\"text-2xl font-semibold text-white\">${pageTitle}</h1>\n <p class=\"mt-2 text-sm text-gray-300\">\n ${isEdit ? 'Update the code example details below' : 'Create a new code snippet or example'}\n </p>\n </div>\n <div class=\"mt-4 sm:mt-0 sm:ml-16 sm:flex-none\">\n <a href=\"/admin/code-examples\"\n class=\"inline-flex items-center justify-center rounded-xl backdrop-blur-sm bg-white/10 px-4 py-2 text-sm font-semibold text-white border border-white/20 hover:bg-white/20 transition-all\">\n <svg class=\"-ml-0.5 mr-1.5 h-5 w-5\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M10 19l-7-7m0 0l7-7m-7 7h18\" />\n </svg>\n Back to List\n </a>\n </div>\n </div>\n\n ${message ? renderAlert({ type: messageType || 'info', message, dismissible: true }) : ''}\n\n <!-- Form -->\n <div class=\"backdrop-blur-xl bg-white/10 rounded-xl border border-white/20 shadow-2xl\">\n <form ${isEdit ? `hx-put=\"/admin/code-examples/${codeExample?.id}\"` : 'hx-post=\"/admin/code-examples\"'}\n hx-target=\"body\"\n hx-swap=\"outerHTML\"\n class=\"space-y-6 p-6\">\n\n <!-- Basic Information Section -->\n <div>\n <h2 class=\"text-lg font-medium text-white mb-4\">Basic Information</h2>\n\n <!-- Title -->\n <div class=\"mb-4\">\n <label for=\"title\" class=\"block text-sm font-medium text-white\">\n Title <span class=\"text-red-400\">*</span>\n </label>\n <div class=\"mt-1\">\n <input type=\"text\"\n name=\"title\"\n id=\"title\"\n value=\"${codeExample?.title || ''}\"\n required\n maxlength=\"200\"\n class=\"block w-full rounded-md border-0 bg-gray-700 py-1.5 text-gray-100 shadow-sm ring-1 ring-inset ring-gray-600 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-purple-600 sm:text-sm sm:leading-6\"\n placeholder=\"e.g., React useState Hook Example\">\n </div>\n ${errors?.title ? `\n <div class=\"mt-1\">\n ${errors.title.map(error => `\n <p class=\"text-sm text-red-400\">${escapeHtml(error)}</p>\n `).join('')}\n </div>\n ` : ''}\n </div>\n\n <!-- Description -->\n <div class=\"mb-4\">\n <label for=\"description\" class=\"block text-sm font-medium text-white\">Description</label>\n <div class=\"mt-1\">\n <textarea name=\"description\"\n id=\"description\"\n rows=\"3\"\n maxlength=\"500\"\n class=\"backdrop-blur-sm bg-white/10 border border-white/20 rounded-xl px-3 py-2 text-white placeholder-gray-300 focus:border-purple-400 focus:outline-none transition-colors w-full\"\n placeholder=\"Briefly describe what this code example demonstrates...\">${codeExample?.description || ''}</textarea>\n <p class=\"mt-1 text-sm text-gray-300\">\n <span id=\"description-count\">0</span>/500 characters\n </p>\n </div>\n ${errors?.description ? `\n <div class=\"mt-1\">\n ${errors.description.map(error => `\n <p class=\"text-sm text-red-400\">${escapeHtml(error)}</p>\n `).join('')}\n </div>\n ` : ''}\n </div>\n\n <div class=\"grid grid-cols-1 md:grid-cols-3 gap-6\">\n <!-- Language -->\n <div>\n <label for=\"language\" class=\"block text-sm font-medium text-white\">\n Language <span class=\"text-red-400\">*</span>\n </label>\n <div class=\"mt-1\">\n <select name=\"language\"\n id=\"language\"\n required\n class=\"block w-full rounded-md border-0 bg-gray-700 py-1.5 text-gray-100 shadow-sm ring-1 ring-inset ring-gray-600 focus:ring-2 focus:ring-inset focus:ring-purple-600 sm:text-sm sm:leading-6\">\n <option value=\"\">Select language...</option>\n <option value=\"javascript\" ${codeExample?.language === 'javascript' ? 'selected' : ''}>JavaScript</option>\n <option value=\"typescript\" ${codeExample?.language === 'typescript' ? 'selected' : ''}>TypeScript</option>\n <option value=\"python\" ${codeExample?.language === 'python' ? 'selected' : ''}>Python</option>\n <option value=\"go\" ${codeExample?.language === 'go' ? 'selected' : ''}>Go</option>\n <option value=\"rust\" ${codeExample?.language === 'rust' ? 'selected' : ''}>Rust</option>\n <option value=\"java\" ${codeExample?.language === 'java' ? 'selected' : ''}>Java</option>\n <option value=\"php\" ${codeExample?.language === 'php' ? 'selected' : ''}>PHP</option>\n <option value=\"ruby\" ${codeExample?.language === 'ruby' ? 'selected' : ''}>Ruby</option>\n <option value=\"sql\" ${codeExample?.language === 'sql' ? 'selected' : ''}>SQL</option>\n </select>\n </div>\n ${errors?.language ? `\n <div class=\"mt-1\">\n ${errors.language.map(error => `\n <p class=\"text-sm text-red-400\">${escapeHtml(error)}</p>\n `).join('')}\n </div>\n ` : ''}\n </div>\n\n <!-- Category -->\n <div>\n <label for=\"category\" class=\"block text-sm font-medium text-white\">Category</label>\n <div class=\"mt-1\">\n <input type=\"text\"\n name=\"category\"\n id=\"category\"\n value=\"${codeExample?.category || ''}\"\n maxlength=\"50\"\n class=\"block w-full rounded-md border-0 bg-gray-700 py-1.5 text-gray-100 shadow-sm ring-1 ring-inset ring-gray-600 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-purple-600 sm:text-sm sm:leading-6\"\n placeholder=\"e.g., frontend, backend\">\n </div>\n ${errors?.category ? `\n <div class=\"mt-1\">\n ${errors.category.map(error => `\n <p class=\"text-sm text-red-400\">${escapeHtml(error)}</p>\n `).join('')}\n </div>\n ` : ''}\n </div>\n\n <!-- Tags -->\n <div>\n <label for=\"tags\" class=\"block text-sm font-medium text-white\">Tags</label>\n <div class=\"mt-1\">\n <input type=\"text\"\n name=\"tags\"\n id=\"tags\"\n value=\"${codeExample?.tags || ''}\"\n maxlength=\"200\"\n class=\"block w-full rounded-md border-0 bg-gray-700 py-1.5 text-gray-100 shadow-sm ring-1 ring-inset ring-gray-600 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-purple-600 sm:text-sm sm:leading-6\"\n placeholder=\"e.g., react, hooks, state\">\n <p class=\"mt-1 text-sm text-gray-300\">Comma-separated tags</p>\n </div>\n ${errors?.tags ? `\n <div class=\"mt-1\">\n ${errors.tags.map(error => `\n <p class=\"text-sm text-red-400\">${escapeHtml(error)}</p>\n `).join('')}\n </div>\n ` : ''}\n </div>\n </div>\n </div>\n\n <!-- Code Section -->\n <div>\n <h2 class=\"text-lg font-medium text-white mb-4\">Code</h2>\n\n <!-- Code Editor -->\n <div class=\"mb-4\">\n <label for=\"code\" class=\"block text-sm font-medium text-white\">\n Code <span class=\"text-red-400\">*</span>\n </label>\n <div class=\"mt-1\">\n <textarea name=\"code\"\n id=\"code\"\n rows=\"20\"\n required\n class=\"backdrop-blur-sm bg-gray-800/90 border border-white/20 rounded-xl px-3 py-2 text-white placeholder-gray-300 focus:border-purple-400 focus:outline-none transition-colors w-full font-mono text-sm\"\n placeholder=\"Paste your code here...\">${codeExample?.code || ''}</textarea>\n <p class=\"mt-1 text-sm text-gray-300\">\n <span id=\"code-count\">0</span> characters\n </p>\n </div>\n ${errors?.code ? `\n <div class=\"mt-1\">\n ${errors.code.map(error => `\n <p class=\"text-sm text-red-400\">${escapeHtml(error)}</p>\n `).join('')}\n </div>\n ` : ''}\n </div>\n </div>\n\n <!-- Status and Sort Order Row -->\n <div class=\"grid grid-cols-1 md:grid-cols-2 gap-6\">\n <!-- Published Status -->\n <div>\n <label class=\"block text-sm font-medium text-white\">Status</label>\n <div class=\"mt-2 space-y-2\">\n <div class=\"flex items-center\">\n <input id=\"published\"\n name=\"isPublished\"\n type=\"radio\"\n value=\"true\"\n ${!codeExample || codeExample.isPublished ? 'checked' : ''}\n class=\"h-4 w-4 text-purple-600 focus:ring-purple-600 border-gray-600 bg-gray-700\">\n <label for=\"published\" class=\"ml-2 block text-sm text-white\">\n Published <span class=\"text-gray-300\">(visible to users)</span>\n </label>\n </div>\n <div class=\"flex items-center\">\n <input id=\"draft\"\n name=\"isPublished\"\n type=\"radio\"\n value=\"false\"\n ${codeExample && !codeExample.isPublished ? 'checked' : ''}\n class=\"h-4 w-4 text-purple-600 focus:ring-purple-600 border-gray-600 bg-gray-700\">\n <label for=\"draft\" class=\"ml-2 block text-sm text-white\">\n Draft <span class=\"text-gray-300\">(not visible to users)</span>\n </label>\n </div>\n </div>\n </div>\n\n <!-- Sort Order -->\n <div>\n <label for=\"sortOrder\" class=\"block text-sm font-medium text-white\">Sort Order</label>\n <div class=\"mt-1\">\n <input type=\"number\"\n name=\"sortOrder\"\n id=\"sortOrder\"\n value=\"${codeExample?.sortOrder || 0}\"\n min=\"0\"\n step=\"1\"\n class=\"block w-full rounded-md border-0 bg-gray-700 py-1.5 text-gray-100 shadow-sm ring-1 ring-inset ring-gray-600 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-purple-600 sm:text-sm sm:leading-6\">\n <p class=\"mt-1 text-sm text-gray-300\">Lower numbers appear first (0 = highest priority)</p>\n </div>\n ${errors?.sortOrder ? `\n <div class=\"mt-1\">\n ${errors.sortOrder.map(error => `\n <p class=\"text-sm text-red-400\">${escapeHtml(error)}</p>\n `).join('')}\n </div>\n ` : ''}\n </div>\n </div>\n\n <!-- Form Actions -->\n <div class=\"flex items-center justify-end space-x-3 pt-6 border-t border-white/20\">\n <a href=\"/admin/code-examples\"\n class=\"inline-flex items-center justify-center rounded-xl backdrop-blur-sm bg-white/10 px-4 py-2 text-sm font-semibold text-white border border-white/20 hover:bg-white/20 transition-all\">\n Cancel\n </a>\n <button type=\"submit\"\n class=\"inline-flex items-center justify-center rounded-xl backdrop-blur-sm bg-purple-500/80 px-4 py-2 text-sm font-semibold text-white border border-white/20 hover:bg-purple-500 transition-all\">\n <svg class=\"-ml-0.5 mr-1.5 h-5 w-5\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M5 13l4 4L19 7\" />\n </svg>\n ${isEdit ? 'Update Code Example' : 'Create Code Example'}\n </button>\n </div>\n </form>\n </div>\n </div>\n\n <script>\n // Character count for description\n const descriptionTextarea = document.getElementById('description');\n const descriptionCount = document.getElementById('description-count');\n\n function updateDescriptionCount() {\n descriptionCount.textContent = descriptionTextarea.value.length;\n }\n\n descriptionTextarea.addEventListener('input', updateDescriptionCount);\n updateDescriptionCount(); // Initial count\n\n // Character count for code\n const codeTextarea = document.getElementById('code');\n const codeCount = document.getElementById('code-count');\n\n function updateCodeCount() {\n codeCount.textContent = codeTextarea.value.length;\n }\n\n codeTextarea.addEventListener('input', updateCodeCount);\n updateCodeCount(); // Initial count\n </script>\n `\n\n const layoutData: AdminLayoutData = {\n title: `${pageTitle} - Admin`,\n pageTitle,\n currentPath: isEdit ? `/admin/code-examples/${codeExample?.id}` : '/admin/code-examples/new',\n user: data.user,\n content: pageContent\n }\n\n return renderAdminLayout(layoutData)\n}\n\nfunction escapeHtml(unsafe: string): string {\n return unsafe\n .replace(/&/g, \"&\")\n .replace(/</g, \"<\")\n .replace(/>/g, \">\")\n .replace(/\"/g, \""\")\n .replace(/'/g, \"'\")\n}\n","import { Hono } from 'hono'\nimport { z } from 'zod'\nimport { renderCodeExamplesList } from '../templates/pages/admin-code-examples-list.template'\nimport { renderCodeExamplesForm } from '../templates/pages/admin-code-examples-form.template'\n\ntype Bindings = {\n DB: D1Database\n KV: KVNamespace\n}\n\ntype Variables = {\n user?: {\n userId: string\n email: string\n role: string\n exp: number\n iat: number\n }\n}\n\nconst codeExampleSchema = z.object({\n title: z.string().min(1, 'Title is required').max(200, 'Title must be under 200 characters'),\n description: z.string().max(500, 'Description must be under 500 characters').optional(),\n code: z.string().min(1, 'Code is required'),\n language: z.string().min(1, 'Language is required'),\n category: z.string().max(50, 'Category must be under 50 characters').optional(),\n tags: z.string().max(200, 'Tags must be under 200 characters').optional(),\n isPublished: z.string().transform(val => val === 'true'),\n sortOrder: z.string().transform(val => parseInt(val, 10)).pipe(z.number().min(0))\n})\n\nconst adminCodeExamplesRoutes = new Hono<{ Bindings: Bindings; Variables: Variables }>()\n\nadminCodeExamplesRoutes.get('/', async (c) => {\n try {\n const user = c.get('user')\n const { published, language, search, page = '1' } = c.req.query()\n const currentPage = parseInt(page, 10) || 1\n const limit = 20\n const offset = (currentPage - 1) * limit\n\n const db = (c as any).env?.DB\n if (!db) {\n return c.html(renderCodeExamplesList({\n codeExamples: [],\n totalCount: 0,\n currentPage: 1,\n totalPages: 1,\n user: user ? {\n name: user.email,\n email: user.email,\n role: user.role\n } : undefined,\n message: 'Database not available',\n messageType: 'error'\n }))\n }\n\n let whereClause = 'WHERE 1=1'\n const params: any[] = []\n\n if (published !== undefined) {\n whereClause += ' AND isPublished = ?'\n params.push(published === 'true' ? 1 : 0)\n }\n\n if (language) {\n whereClause += ' AND language = ?'\n params.push(language)\n }\n\n if (search) {\n whereClause += ' AND (title LIKE ? OR description LIKE ? OR code LIKE ? OR tags LIKE ?)'\n const searchTerm = `%${search}%`\n params.push(searchTerm, searchTerm, searchTerm, searchTerm)\n }\n\n const countQuery = `SELECT COUNT(*) as count FROM code_examples ${whereClause}`\n const { results: countResults } = await db.prepare(countQuery).bind(...params).all()\n const totalCount = countResults?.[0]?.count || 0\n\n const dataQuery = `\n SELECT * FROM code_examples\n ${whereClause}\n ORDER BY sortOrder ASC, created_at DESC\n LIMIT ? OFFSET ?\n `\n const { results: codeExamples } = await db.prepare(dataQuery).bind(...params, limit, offset).all()\n\n const totalPages = Math.ceil(totalCount / limit)\n\n return c.html(renderCodeExamplesList({\n codeExamples: codeExamples || [],\n totalCount,\n currentPage,\n totalPages,\n user: user ? {\n name: user.email,\n email: user.email,\n role: user.role\n } : undefined\n }))\n } catch (error) {\n console.error('Error fetching code examples:', error)\n const user = c.get('user')\n return c.html(renderCodeExamplesList({\n codeExamples: [],\n totalCount: 0,\n currentPage: 1,\n totalPages: 1,\n user: user ? {\n name: user.email,\n email: user.email,\n role: user.role\n } : undefined,\n message: 'Failed to load code examples',\n messageType: 'error'\n }))\n }\n})\n\nadminCodeExamplesRoutes.get('/new', async (c) => {\n const user = c.get('user')\n return c.html(renderCodeExamplesForm({\n isEdit: false,\n user: user ? {\n name: user.email,\n email: user.email,\n role: user.role\n } : undefined\n }))\n})\n\nadminCodeExamplesRoutes.post('/', async (c) => {\n try {\n const formData = await c.req.formData()\n const data = Object.fromEntries(formData.entries())\n\n const validatedData = codeExampleSchema.parse(data)\n const user = c.get('user')\n const db = (c as any).env?.DB\n\n if (!db) {\n return c.html(renderCodeExamplesForm({\n isEdit: false,\n user: user ? {\n name: user.email,\n email: user.email,\n role: user.role\n } : undefined,\n message: 'Database not available',\n messageType: 'error'\n }))\n }\n\n const { results } = await db.prepare(`\n INSERT INTO code_examples (title, description, code, language, category, tags, isPublished, sortOrder)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?)\n RETURNING *\n `).bind(\n validatedData.title,\n validatedData.description || null,\n validatedData.code,\n validatedData.language,\n validatedData.category || null,\n validatedData.tags || null,\n validatedData.isPublished ? 1 : 0,\n validatedData.sortOrder\n ).all()\n\n if (results && results.length > 0) {\n return c.redirect('/admin/code-examples?message=Code example created successfully')\n } else {\n return c.html(renderCodeExamplesForm({\n isEdit: false,\n user: user ? {\n name: user.email,\n email: user.email,\n role: user.role\n } : undefined,\n message: 'Failed to create code example',\n messageType: 'error'\n }))\n }\n } catch (error) {\n console.error('Error creating code example:', error)\n const user = c.get('user')\n\n if (error instanceof z.ZodError) {\n const errors: Record<string, string[]> = {}\n error.issues.forEach(err => {\n const field = err.path[0] as string\n if (!errors[field]) errors[field] = []\n errors[field].push(err.message)\n })\n\n return c.html(renderCodeExamplesForm({\n isEdit: false,\n user: user ? {\n name: user.email,\n email: user.email,\n role: user.role\n } : undefined,\n errors,\n message: 'Please correct the errors below',\n messageType: 'error'\n }))\n }\n\n return c.html(renderCodeExamplesForm({\n isEdit: false,\n user: user ? {\n name: user.email,\n email: user.email,\n role: user.role\n } : undefined,\n message: 'Failed to create code example',\n messageType: 'error'\n }))\n }\n})\n\nadminCodeExamplesRoutes.get('/:id', async (c) => {\n try {\n const id = parseInt(c.req.param('id'))\n const user = c.get('user')\n const db = (c as any).env?.DB\n\n if (!db) {\n return c.html(renderCodeExamplesForm({\n isEdit: true,\n user: user ? {\n name: user.email,\n email: user.email,\n role: user.role\n } : undefined,\n message: 'Database not available',\n messageType: 'error'\n }))\n }\n\n const { results } = await db.prepare('SELECT * FROM code_examples WHERE id = ?').bind(id).all()\n\n if (!results || results.length === 0) {\n return c.redirect('/admin/code-examples?message=Code example not found&type=error')\n }\n\n const example = results[0] as any\n\n return c.html(renderCodeExamplesForm({\n codeExample: {\n id: example.id,\n title: example.title,\n description: example.description,\n code: example.code,\n language: example.language,\n category: example.category,\n tags: example.tags,\n isPublished: Boolean(example.isPublished),\n sortOrder: example.sortOrder\n },\n isEdit: true,\n user: user ? {\n name: user.email,\n email: user.email,\n role: user.role\n } : undefined\n }))\n } catch (error) {\n console.error('Error fetching code example:', error)\n const user = c.get('user')\n return c.html(renderCodeExamplesForm({\n isEdit: true,\n user: user ? {\n name: user.email,\n email: user.email,\n role: user.role\n } : undefined,\n message: 'Failed to load code example',\n messageType: 'error'\n }))\n }\n})\n\nadminCodeExamplesRoutes.put('/:id', async (c) => {\n try {\n const id = parseInt(c.req.param('id'))\n const formData = await c.req.formData()\n const data = Object.fromEntries(formData.entries())\n\n const validatedData = codeExampleSchema.parse(data)\n const user = c.get('user')\n const db = (c as any).env?.DB\n\n if (!db) {\n return c.html(renderCodeExamplesForm({\n isEdit: true,\n user: user ? {\n name: user.email,\n email: user.email,\n role: user.role\n } : undefined,\n message: 'Database not available',\n messageType: 'error'\n }))\n }\n\n const { results } = await db.prepare(`\n UPDATE code_examples\n SET title = ?, description = ?, code = ?, language = ?, category = ?, tags = ?, isPublished = ?, sortOrder = ?\n WHERE id = ?\n RETURNING *\n `).bind(\n validatedData.title,\n validatedData.description || null,\n validatedData.code,\n validatedData.language,\n validatedData.category || null,\n validatedData.tags || null,\n validatedData.isPublished ? 1 : 0,\n validatedData.sortOrder,\n id\n ).all()\n\n if (results && results.length > 0) {\n return c.redirect('/admin/code-examples?message=Code example updated successfully')\n } else {\n return c.html(renderCodeExamplesForm({\n codeExample: {\n id,\n title: validatedData.title,\n description: validatedData.description,\n code: validatedData.code,\n language: validatedData.language,\n category: validatedData.category,\n tags: validatedData.tags,\n isPublished: validatedData.isPublished,\n sortOrder: validatedData.sortOrder\n },\n isEdit: true,\n user: user ? {\n name: user.email,\n email: user.email,\n role: user.role\n } : undefined,\n message: 'Code example not found',\n messageType: 'error'\n }))\n }\n } catch (error) {\n console.error('Error updating code example:', error)\n const user = c.get('user')\n const id = parseInt(c.req.param('id'))\n\n if (error instanceof z.ZodError) {\n const errors: Record<string, string[]> = {}\n error.issues.forEach(err => {\n const field = err.path[0] as string\n if (!errors[field]) errors[field] = []\n errors[field].push(err.message)\n })\n\n return c.html(renderCodeExamplesForm({\n codeExample: {\n id,\n title: '',\n description: '',\n code: '',\n language: '',\n category: '',\n tags: '',\n isPublished: true,\n sortOrder: 0\n },\n isEdit: true,\n user: user ? {\n name: user.email,\n email: user.email,\n role: user.role\n } : undefined,\n errors,\n message: 'Please correct the errors below',\n messageType: 'error'\n }))\n }\n\n return c.html(renderCodeExamplesForm({\n codeExample: {\n id,\n title: '',\n description: '',\n code: '',\n language: '',\n category: '',\n tags: '',\n isPublished: true,\n sortOrder: 0\n },\n isEdit: true,\n user: user ? {\n name: user.email,\n email: user.email,\n role: user.role\n } : undefined,\n message: 'Failed to update code example',\n messageType: 'error'\n }))\n }\n})\n\nadminCodeExamplesRoutes.delete('/:id', async (c) => {\n try {\n const id = parseInt(c.req.param('id'))\n const db = (c as any).env?.DB\n\n if (!db) {\n return c.json({ error: 'Database not available' }, 500)\n }\n\n const { changes } = await db.prepare('DELETE FROM code_examples WHERE id = ?').bind(id).run()\n\n if (changes === 0) {\n return c.json({ error: 'Code example not found' }, 404)\n }\n\n return c.redirect('/admin/code-examples?message=Code example deleted successfully')\n } catch (error) {\n console.error('Error deleting code example:', error)\n return c.json({ error: 'Failed to delete code example' }, 500)\n }\n})\n\nexport default adminCodeExamplesRoutes\n","import {\n AdminLayoutData,\n renderAdminLayout,\n} from \"../layouts/admin-layout-v2.template\";\n\nexport interface DashboardStats {\n collections: number;\n contentItems: number;\n mediaFiles: number;\n users: number;\n databaseSize?: number; // Size in bytes\n mediaSize?: number; // Total size of all media files in bytes\n recentActivity?: ActivityItem[];\n analytics?: AnalyticsData;\n}\n\nexport interface ActivityItem {\n id: string;\n type: \"content\" | \"media\" | \"user\" | \"collection\";\n action: string;\n description: string;\n timestamp: string;\n user: string;\n}\n\nexport interface AnalyticsData {\n pageViews: number;\n uniqueVisitors: number;\n contentPublished: number;\n mediaUploaded: number;\n weeklyGrowth: {\n pageViews: number;\n visitors: number;\n content: number;\n media: number;\n };\n}\n\nexport interface DashboardPageData {\n user?: {\n name: string;\n email: string;\n role: string;\n };\n stats?: DashboardStats;\n version?: string;\n enableExperimentalFeatures?: boolean;\n}\n\nexport function renderDashboardPage(data: DashboardPageData): string {\n const pageContent = `\n <div class=\"mb-8 flex flex-col sm:flex-row sm:items-center sm:justify-between\">\n <div>\n <h1 class=\"text-2xl/8 font-semibold text-zinc-950 dark:text-white sm:text-xl/8\">Dashboard</h1>\n <p class=\"mt-2 text-sm/6 text-zinc-500 dark:text-zinc-400\">Welcome to your SonicJS AI admin dashboard</p>\n </div>\n <div class=\"mt-4 sm:mt-0 flex items-center gap-x-3\">\n <a href=\"https://sonicjs.com/installation\" target=\"_blank\" class=\"inline-flex items-center justify-center gap-x-1.5 rounded-lg bg-lime-600 dark:bg-lime-700 px-3.5 py-2.5 text-sm font-semibold text-white hover:bg-lime-700 dark:hover:bg-lime-600 transition-colors shadow-sm\">\n <svg class=\"h-5 w-5\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\" stroke-width=\"1.5\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M4.26 10.147a60.436 60.436 0 00-.491 6.347A48.627 48.627 0 0112 20.904a48.627 48.627 0 018.232-4.41 60.46 60.46 0 00-.491-6.347m-15.482 0a50.57 50.57 0 00-2.658-.813A59.905 59.905 0 0112 3.493a59.902 59.902 0 0110.399 5.84c-.896.248-1.783.52-2.658.814m-15.482 0A50.697 50.697 0 0112 13.489a50.702 50.702 0 017.74-3.342M6.75 15a.75.75 0 100-1.5.75.75 0 000 1.5zm0 0v-3.675A55.378 55.378 0 0112 8.443m-7.007 11.55A5.981 5.981 0 006.75 15.75v-1.5\"/>\n </svg>\n Developer Docs\n </a>\n <a href=\"/admin/api-reference\" class=\"inline-flex items-center justify-center gap-x-1.5 rounded-lg bg-white dark:bg-zinc-800 px-3.5 py-2.5 text-sm font-semibold text-zinc-950 dark:text-white ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 hover:bg-zinc-50 dark:hover:bg-zinc-700 transition-colors shadow-sm\">\n <svg class=\"h-5 w-5\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\" stroke-width=\"1.5\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M12 6.042A8.967 8.967 0 006 3.75c-1.052 0-2.062.18-3 .512v14.25A8.987 8.987 0 016 18c2.305 0 4.408.867 6 2.292m0-14.25a8.966 8.966 0 016-2.292c1.052 0 2.062.18 3 .512v14.25A8.987 8.987 0 0018 18a8.967 8.967 0 00-6 2.292m0-14.25v14.25\"/>\n </svg>\n API Docs\n </a>\n <a href=\"/api\" target=\"_blank\" class=\"inline-flex items-center justify-center gap-x-1.5 rounded-lg bg-zinc-950 dark:bg-white px-3.5 py-2.5 text-sm font-semibold text-white dark:text-zinc-950 hover:bg-zinc-800 dark:hover:bg-zinc-100 transition-colors shadow-sm\">\n <svg class=\"h-5 w-5\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\" stroke-width=\"1.5\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M17.25 6.75L22.5 12l-5.25 5.25m-10.5 0L1.5 12l5.25-5.25m7.5-3l-4.5 16.5\"/>\n </svg>\n OpenAPI\n </a>\n </div>\n </div>\n\n <!-- Stats Cards -->\n <div\n id=\"stats-container\"\n class=\"mb-8\"\n hx-get=\"/admin/dashboard/stats\"\n hx-trigger=\"load\"\n hx-swap=\"innerHTML\"\n >\n ${renderStatsCardsSkeleton()}\n </div>\n\n <!-- Dashboard Grid -->\n <div class=\"grid grid-cols-1 gap-6 xl:grid-cols-3 mb-8\">\n <!-- Analytics Chart -->\n <div class=\"xl:col-span-2\">\n ${renderAnalyticsChart()}\n </div>\n\n <!-- Recent Activity -->\n <div\n class=\"xl:col-span-1\"\n id=\"recent-activity-container\"\n hx-get=\"/admin/dashboard/recent-activity\"\n hx-trigger=\"load\"\n hx-swap=\"innerHTML\"\n >\n ${renderRecentActivitySkeleton()}\n </div>\n </div>\n\n <!-- Secondary Grid -->\n <div class=\"grid grid-cols-1 gap-6 lg:grid-cols-3\">\n <!-- Quick Actions -->\n ${renderQuickActions()}\n\n <!-- System Status -->\n ${renderSystemStatus()}\n\n <!-- Storage Usage -->\n <div id=\"storage-usage-container\" hx-get=\"/admin/dashboard/storage\" hx-trigger=\"load\" hx-swap=\"innerHTML\">\n ${renderStorageUsage()}\n </div>\n </div>\n\n <script>\n function refreshDashboard() {\n htmx.trigger('#stats-container', 'htmx:load');\n showNotification('Dashboard refreshed', 'success');\n }\n </script>\n `;\n\n const layoutData: AdminLayoutData = {\n title: \"Dashboard\",\n pageTitle: \"Dashboard\",\n currentPath: \"/admin\",\n user: data.user,\n version: data.version,\n content: pageContent,\n };\n\n return renderAdminLayout(layoutData);\n}\n\nexport function renderDashboardPageWithDynamicMenu(\n data: DashboardPageData,\n dynamicMenuItems: Array<{ label: string; path: string; icon: string }>\n): string {\n const pageContent = `\n <div class=\"mb-8 flex flex-col sm:flex-row sm:items-center sm:justify-between\">\n <div>\n <h1 class=\"text-2xl/8 font-semibold text-zinc-950 dark:text-white sm:text-xl/8\">Dashboard</h1>\n <p class=\"mt-2 text-sm/6 text-zinc-500 dark:text-zinc-400\">Welcome to your SonicJS AI admin dashboard</p>\n </div>\n <div class=\"mt-4 sm:mt-0 flex items-center gap-x-3\">\n <a href=\"/admin/api-reference\" class=\"inline-flex items-center justify-center gap-x-1.5 rounded-lg bg-white dark:bg-zinc-800 px-3.5 py-2.5 text-sm font-semibold text-zinc-950 dark:text-white ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 hover:bg-zinc-50 dark:hover:bg-zinc-700 transition-colors shadow-sm\">\n <svg class=\"h-5 w-5\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\" stroke-width=\"1.5\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M12 6.042A8.967 8.967 0 006 3.75c-1.052 0-2.062.18-3 .512v14.25A8.987 8.987 0 016 18c2.305 0 4.408.867 6 2.292m0-14.25a8.966 8.966 0 016-2.292c1.052 0 2.062.18 3 .512v14.25A8.987 8.987 0 0018 18a8.967 8.967 0 00-6 2.292m0-14.25v14.25\"/>\n </svg>\n API Docs\n </a>\n <a href=\"/api\" target=\"_blank\" class=\"inline-flex items-center justify-center gap-x-1.5 rounded-lg bg-zinc-950 dark:bg-white px-3.5 py-2.5 text-sm font-semibold text-white dark:text-zinc-950 hover:bg-zinc-800 dark:hover:bg-zinc-100 transition-colors shadow-sm\">\n <svg class=\"h-5 w-5\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\" stroke-width=\"1.5\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M17.25 6.75L22.5 12l-5.25 5.25m-10.5 0L1.5 12l5.25-5.25m7.5-3l-4.5 16.5\"/>\n </svg>\n OpenAPI\n </a>\n </div>\n </div>\n\n <div id=\"stats-container\" class=\"mb-8\" hx-get=\"/admin/dashboard/stats\" hx-trigger=\"load\">\n ${renderStatsCards({\n collections: 0,\n contentItems: 0,\n mediaFiles: 0,\n users: 0,\n })}\n </div>\n\n <div class=\"grid grid-cols-1 gap-6 xl:grid-cols-3 mb-8\">\n <!-- Analytics Chart -->\n <div class=\"xl:col-span-2\">\n ${renderAnalyticsChart()}\n </div>\n\n <!-- Recent Activity -->\n <div\n class=\"xl:col-span-1\"\n id=\"recent-activity-container\"\n hx-get=\"/admin/dashboard/recent-activity\"\n hx-trigger=\"load\"\n hx-swap=\"innerHTML\"\n >\n ${renderRecentActivitySkeleton()}\n </div>\n </div>\n\n <div class=\"grid grid-cols-1 gap-6 lg:grid-cols-3\">\n <!-- Quick Actions -->\n ${renderQuickActions()}\n\n <!-- System Status -->\n ${renderSystemStatus()}\n\n <!-- Storage Usage -->\n <div id=\"storage-usage-container\" hx-get=\"/admin/dashboard/storage\" hx-trigger=\"load\" hx-swap=\"innerHTML\">\n ${renderStorageUsage()}\n </div>\n </div>\n\n <script>\n function refreshDashboard() {\n htmx.trigger('#stats-container', 'htmx:load');\n showNotification('Dashboard refreshed', 'success');\n }\n </script>\n `;\n\n const layoutData: AdminLayoutData = {\n title: \"Dashboard\",\n pageTitle: \"Dashboard\",\n currentPath: \"/admin\",\n user: data.user,\n version: data.version,\n enableExperimentalFeatures: data.enableExperimentalFeatures,\n content: pageContent,\n dynamicMenuItems,\n };\n\n return renderAdminLayout(layoutData);\n}\n\nexport function renderStatsCards(stats: DashboardStats): string {\n const cards = [\n {\n title: \"Total Collections\",\n value: stats.collections.toString(),\n change: \"12.5\",\n isPositive: true,\n },\n {\n title: \"Content Items\",\n value: stats.contentItems.toString(),\n change: \"8.2\",\n isPositive: true,\n },\n {\n title: \"Media Files\",\n value: stats.mediaFiles.toString(),\n change: \"15.3\",\n isPositive: true,\n },\n {\n title: \"Active Users\",\n value: stats.users.toString(),\n change: \"2.4\",\n isPositive: false,\n },\n ];\n\n const cardColors = ['text-cyan-400', 'text-lime-400', 'text-pink-400', 'text-purple-400'];\n\n return `\n <div>\n <h3 class=\"text-base font-semibold text-zinc-950 dark:text-white\">Last 30 days</h3>\n <dl class=\"mt-5 grid grid-cols-1 divide-zinc-950/5 dark:divide-white/10 overflow-hidden rounded-lg bg-zinc-800/75 dark:bg-zinc-800/75 ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 md:grid-cols-4 md:divide-x md:divide-y-0\">\n ${cards.map((card, index) => `\n <div class=\"px-4 py-5 sm:p-6\">\n <dt class=\"text-base font-normal text-zinc-700 dark:text-zinc-100\">${card.title}</dt>\n <dd class=\"mt-1 flex items-baseline justify-between md:block lg:flex\">\n <div class=\"flex items-baseline text-2xl font-semibold ${cardColors[index]}\">\n ${card.value}\n </div>\n <div class=\"inline-flex items-baseline rounded-full ${card.isPositive ? 'bg-lime-400/10 text-lime-600 dark:text-lime-400' : 'bg-pink-400/10 text-pink-600 dark:text-pink-400'} px-2.5 py-0.5 text-sm font-medium md:mt-2 lg:mt-0\">\n <svg viewBox=\"0 0 20 20\" fill=\"currentColor\" class=\"-ml-1 mr-0.5 size-5 shrink-0 self-center\">\n ${card.isPositive\n ? '<path d=\"M10 17a.75.75 0 0 1-.75-.75V5.612L5.29 9.77a.75.75 0 0 1-1.08-1.04l5.25-5.5a.75.75 0 0 1 1.08 0l5.25 5.5a.75.75 0 1 1-1.08 1.04l-3.96-4.158V16.25A.75.75 0 0 1 10 17Z\" clip-rule=\"evenodd\" fill-rule=\"evenodd\" />'\n : '<path d=\"M10 3a.75.75 0 0 1 .75.75v10.638l3.96-4.158a.75.75 0 1 1 1.08 1.04l-5.25 5.5a.75.75 0 0 1-1.08 0l-5.25-5.5a.75.75 0 1 1 1.08-1.04l3.96 4.158V3.75A.75.75 0 0 1 10 3Z\" clip-rule=\"evenodd\" fill-rule=\"evenodd\" />'\n }\n </svg>\n <span class=\"sr-only\">${card.isPositive ? 'Increased' : 'Decreased'} by</span>\n ${card.change}%\n </div>\n </dd>\n </div>\n `).join('')}\n </dl>\n </div>\n `;\n}\n\nfunction renderStatsCardsSkeleton(): string {\n return `\n <div>\n <div class=\"h-6 w-32 bg-zinc-200 dark:bg-zinc-700 rounded animate-pulse mb-5\"></div>\n <div class=\"grid grid-cols-1 divide-zinc-950/5 dark:divide-white/10 overflow-hidden rounded-lg bg-zinc-800/75 dark:bg-zinc-800/75 ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 md:grid-cols-4 md:divide-x md:divide-y-0\">\n ${Array(4)\n .fill(0)\n .map(\n () => `\n <div class=\"px-4 py-5 sm:p-6 animate-pulse\">\n <div class=\"h-4 w-24 bg-zinc-200 dark:bg-zinc-700 rounded mb-3\"></div>\n <div class=\"h-8 w-16 bg-zinc-200 dark:bg-zinc-700 rounded\"></div>\n </div>\n `\n )\n .join(\"\")}\n </div>\n </div>\n `;\n}\n\nfunction renderAnalyticsChart(): string {\n return `\n <div class=\"rounded-lg bg-white dark:bg-zinc-900 shadow-sm ring-1 ring-zinc-950/5 dark:ring-white/10\">\n <div class=\"border-b border-zinc-950/5 dark:border-white/10 px-6 py-6\">\n <div class=\"flex flex-wrap items-start justify-between gap-3 sm:flex-nowrap\">\n <div>\n <h3 class=\"text-base/7 font-semibold text-zinc-950 dark:text-white\">Real-Time Analytics</h3>\n <p class=\"mt-1 text-sm/6 text-zinc-500 dark:text-zinc-400\">Requests per second (live)</p>\n </div>\n <div class=\"flex items-center gap-2\">\n <div class=\"h-2 w-2 rounded-full bg-lime-500 animate-pulse\"></div>\n <span class=\"text-xs text-zinc-500 dark:text-zinc-400\">Live</span>\n </div>\n </div>\n <div class=\"mt-4 flex items-baseline gap-2\">\n <span id=\"current-rps\" class=\"text-4xl font-bold text-cyan-500 dark:text-cyan-400\">0</span>\n <span class=\"text-sm text-zinc-500 dark:text-zinc-400\">req/s</span>\n </div>\n </div>\n\n <div class=\"px-6 py-6\">\n <canvas id=\"requestsChart\" class=\"w-full\" style=\"height: 300px;\"></canvas>\n </div>\n\n <!-- Hidden div to trigger HTMX polling -->\n <div\n hx-get=\"/admin/dashboard/api/metrics\"\n hx-trigger=\"every 1s\"\n hx-swap=\"none\"\n style=\"display: none;\"\n ></div>\n </div>\n\n <script>\n // Initialize Chart.js for Real-time Requests\n (function() {\n const ctx = document.getElementById('requestsChart');\n if (!ctx) return;\n\n // Initialize with last 60 seconds of data (1 data point per second)\n const maxDataPoints = 60;\n const labels = [];\n const data = [];\n\n for (let i = maxDataPoints - 1; i >= 0; i--) {\n labels.push(\\`-\\${i}s\\`);\n data.push(0);\n }\n\n const isDark = document.documentElement.classList.contains('dark');\n\n const chart = new Chart(ctx, {\n type: 'line',\n data: {\n labels: labels,\n datasets: [{\n label: 'Requests/sec',\n data: data,\n borderColor: isDark ? 'rgb(34, 211, 238)' : 'rgb(6, 182, 212)',\n backgroundColor: isDark ? 'rgba(34, 211, 238, 0.1)' : 'rgba(6, 182, 212, 0.1)',\n borderWidth: 2,\n fill: true,\n tension: 0.4,\n pointRadius: 0,\n pointHoverRadius: 4,\n pointBackgroundColor: isDark ? 'rgb(34, 211, 238)' : 'rgb(6, 182, 212)',\n pointBorderColor: isDark ? 'rgb(17, 24, 39)' : 'rgb(255, 255, 255)',\n pointBorderWidth: 2\n }]\n },\n options: {\n responsive: true,\n maintainAspectRatio: false,\n plugins: {\n legend: {\n display: false\n },\n tooltip: {\n backgroundColor: isDark ? 'rgb(39, 39, 42)' : 'rgb(255, 255, 255)',\n titleColor: isDark ? 'rgb(255, 255, 255)' : 'rgb(9, 9, 11)',\n bodyColor: isDark ? 'rgb(161, 161, 170)' : 'rgb(113, 113, 122)',\n borderColor: isDark ? 'rgba(255, 255, 255, 0.1)' : 'rgba(9, 9, 11, 0.05)',\n borderWidth: 1,\n padding: 12,\n displayColors: false,\n callbacks: {\n label: function(context) {\n return 'Requests/sec: ' + context.parsed.y.toFixed(2);\n }\n }\n }\n },\n scales: {\n y: {\n beginAtZero: true,\n border: {\n display: false\n },\n grid: {\n color: isDark ? 'rgba(255, 255, 255, 0.05)' : 'rgba(0, 0, 0, 0.05)',\n drawBorder: false\n },\n ticks: {\n color: isDark ? 'rgb(161, 161, 170)' : 'rgb(113, 113, 122)',\n padding: 8,\n callback: function(value) {\n return value.toFixed(1);\n }\n }\n },\n x: {\n border: {\n display: false\n },\n grid: {\n display: false\n },\n ticks: {\n color: isDark ? 'rgb(161, 161, 170)' : 'rgb(113, 113, 122)',\n padding: 8,\n maxTicksLimit: 6\n }\n }\n }\n }\n });\n\n // Listen for metrics updates from HTMX\n window.addEventListener('htmx:afterRequest', function(event) {\n console.log('[Dashboard] HTMX request completed:', event.detail.pathInfo.requestPath);\n\n if (event.detail.pathInfo.requestPath === '/admin/dashboard/api/metrics') {\n try {\n const metrics = JSON.parse(event.detail.xhr.responseText);\n console.log('[Dashboard] Metrics received:', metrics);\n\n // Update current RPS display\n const rpsElement = document.getElementById('current-rps');\n if (rpsElement) {\n rpsElement.textContent = metrics.requestsPerSecond.toFixed(2);\n }\n\n // Add new data point to chart\n chart.data.datasets[0].data.shift();\n chart.data.datasets[0].data.push(metrics.requestsPerSecond);\n\n // Regenerate labels to maintain -60s to now format\n const newLabels = [];\n for (let i = maxDataPoints - 1; i >= 1; i--) {\n newLabels.push(\\`-\\${i}s\\`);\n }\n newLabels.push('now');\n chart.data.labels = newLabels;\n\n chart.update('none'); // Update without animation for smoother real-time updates\n console.log('[Dashboard] Chart updated with RPS:', metrics.requestsPerSecond);\n } catch (e) {\n console.error('[Dashboard] Error updating metrics:', e);\n }\n }\n });\n })();\n </script>\n `;\n}\n\nexport function renderRecentActivitySkeleton(): string {\n return `\n <div class=\"rounded-lg bg-white dark:bg-zinc-900 shadow-sm ring-1 ring-zinc-950/5 dark:ring-white/10 animate-pulse\">\n <div class=\"border-b border-zinc-950/5 dark:border-white/10 px-6 py-6\">\n <div class=\"h-5 w-32 bg-zinc-200 dark:bg-zinc-700 rounded\"></div>\n </div>\n <div class=\"px-6 py-6\">\n <div class=\"space-y-6\">\n ${Array(3).fill(0).map(() => `\n <div class=\"flex gap-x-4\">\n <div class=\"h-10 w-10 rounded-full bg-zinc-200 dark:bg-zinc-700\"></div>\n <div class=\"flex-auto space-y-2\">\n <div class=\"h-4 w-48 bg-zinc-200 dark:bg-zinc-700 rounded\"></div>\n <div class=\"h-3 w-32 bg-zinc-200 dark:bg-zinc-700 rounded\"></div>\n </div>\n </div>\n `).join('')}\n </div>\n </div>\n </div>\n `\n}\n\nexport function renderRecentActivity(activities?: ActivityItem[]): string {\n // Helper to get user initials\n const getInitials = (user: string): string => {\n const parts = user.split(' ').filter(p => p.length > 0)\n if (parts.length >= 2) {\n const first = parts[0]?.[0] || ''\n const second = parts[1]?.[0] || ''\n return (first + second).toUpperCase()\n }\n return user.substring(0, 2).toUpperCase()\n }\n\n // Helper to get relative time\n const getRelativeTime = (timestamp: string): string => {\n const date = new Date(timestamp)\n const now = new Date()\n const diffMs = now.getTime() - date.getTime()\n const diffMins = Math.floor(diffMs / 60000)\n const diffHours = Math.floor(diffMins / 60)\n const diffDays = Math.floor(diffHours / 24)\n\n if (diffMins < 1) return 'just now'\n if (diffMins < 60) return `${diffMins} minute${diffMins > 1 ? 's' : ''} ago`\n if (diffHours < 24) return `${diffHours} hour${diffHours > 1 ? 's' : ''} ago`\n return `${diffDays} day${diffDays > 1 ? 's' : ''} ago`\n }\n\n // Helper to get color classes based on activity type\n const getColorClasses = (type: string): { bgColor: string; textColor: string } => {\n switch (type) {\n case 'content':\n return {\n bgColor: 'bg-lime-500/10 dark:bg-lime-400/10',\n textColor: 'text-lime-700 dark:text-lime-300'\n }\n case 'media':\n return {\n bgColor: 'bg-cyan-500/10 dark:bg-cyan-400/10',\n textColor: 'text-cyan-700 dark:text-cyan-300'\n }\n case 'user':\n return {\n bgColor: 'bg-pink-500/10 dark:bg-pink-400/10',\n textColor: 'text-pink-700 dark:text-pink-300'\n }\n case 'collection':\n return {\n bgColor: 'bg-purple-500/10 dark:bg-purple-400/10',\n textColor: 'text-purple-700 dark:text-purple-300'\n }\n default:\n return {\n bgColor: 'bg-gray-500/10 dark:bg-gray-400/10',\n textColor: 'text-gray-700 dark:text-gray-300'\n }\n }\n }\n\n // Format activities with colors and times\n const formattedActivities = (activities || []).map(activity => {\n const colors = getColorClasses(activity.type)\n return {\n ...activity,\n initials: getInitials(activity.user),\n time: getRelativeTime(activity.timestamp),\n ...colors\n }\n })\n\n // If no activities, show empty state\n if (formattedActivities.length === 0) {\n formattedActivities.push({\n type: 'content' as const,\n description: 'No recent activity',\n user: 'System',\n time: '',\n initials: 'SY',\n bgColor: 'bg-gray-500/10 dark:bg-gray-400/10',\n textColor: 'text-gray-700 dark:text-gray-300',\n id: '0',\n action: '',\n timestamp: new Date().toISOString()\n })\n }\n\n return `\n <div class=\"rounded-lg bg-white dark:bg-zinc-900 shadow-sm ring-1 ring-zinc-950/5 dark:ring-white/10\">\n <div class=\"border-b border-zinc-950/5 dark:border-white/10 px-6 py-6\">\n <div class=\"flex items-center justify-between\">\n <h3 class=\"text-base/7 font-semibold text-zinc-950 dark:text-white\">Recent Activity</h3>\n <button class=\"text-xs/5 font-medium text-zinc-500 hover:text-zinc-700 dark:text-zinc-400 dark:hover:text-zinc-300 transition-colors\">\n View all\n </button>\n </div>\n </div>\n\n <div class=\"px-6 py-6\">\n <ul role=\"list\" class=\"space-y-6\">\n ${formattedActivities\n .map(\n (activity) => `\n <li class=\"relative flex gap-x-4\">\n <div class=\"flex h-10 w-10 flex-none items-center justify-center rounded-full ${activity.bgColor}\">\n <span class=\"text-xs font-semibold ${activity.textColor}\">${activity.initials}</span>\n </div>\n <div class=\"flex-auto\">\n <p class=\"text-sm/6 font-medium text-zinc-950 dark:text-white\">${activity.description}</p>\n <p class=\"mt-1 text-xs/5 text-zinc-500 dark:text-zinc-400\">\n <span class=\"font-medium text-zinc-950 dark:text-white\">${activity.user}</span>\n <span class=\"text-zinc-400 dark:text-zinc-500\"> · </span>\n ${activity.time}\n </p>\n </div>\n </li>\n `\n )\n .join(\"\")}\n </ul>\n </div>\n </div>\n `;\n}\n\nfunction renderQuickActions(): string {\n const actions = [\n {\n title: \"Create Content\",\n description: \"Add new blog post or page\",\n href: \"/admin/content/new\",\n icon: `<svg class=\"w-5 h-5\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M12 4v16m8-8H4\"/>\n </svg>`,\n },\n {\n title: \"Upload Media\",\n description: \"Add images and files\",\n href: \"/admin/media\",\n icon: `<svg class=\"w-5 h-5\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M7 16a4 4 0 01-.88-7.903A5 5 0 1115.9 6L16 6a5 5 0 011 9.9M15 13l-3-3m0 0l-3 3m3-3v12\"/>\n </svg>`,\n },\n {\n title: \"Manage Users\",\n description: \"Add or edit user accounts\",\n href: \"/admin/users\",\n icon: `<svg class=\"w-5 h-5\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M12 4.354a4 4 0 110 5.292M15 21H3v-1a6 6 0 0112 0v1zm0 0h6v-1a6 6 0 00-9-5.197M13 7a4 4 0 11-8 0 4 4 0 018 0z\"/>\n </svg>`,\n },\n ];\n\n return `\n <div class=\"rounded-lg bg-white dark:bg-zinc-900 shadow-sm ring-1 ring-zinc-950/5 dark:ring-white/10\">\n <div class=\"border-b border-zinc-950/5 dark:border-white/10 px-6 py-6\">\n <h3 class=\"text-base/7 font-semibold text-zinc-950 dark:text-white\">Quick Actions</h3>\n </div>\n\n <div class=\"p-6\">\n <div class=\"space-y-2\">\n ${actions\n .map(\n (action) => `\n <a href=\"${action.href}\" class=\"group flex items-center gap-x-3 rounded-lg px-3 py-2 hover:bg-zinc-50 dark:hover:bg-zinc-800/50 transition-colors\">\n <div class=\"flex h-10 w-10 flex-none items-center justify-center text-zinc-400 dark:text-zinc-500 group-hover:text-zinc-600 dark:group-hover:text-zinc-400\">\n ${action.icon}\n </div>\n <div class=\"flex-auto\">\n <p class=\"text-sm/6 font-medium text-zinc-950 dark:text-white\">${action.title}</p>\n <p class=\"text-xs/5 text-zinc-500 dark:text-zinc-400\">${action.description}</p>\n </div>\n <svg class=\"h-5 w-5 flex-none text-zinc-400 dark:text-zinc-500\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"1.5\" d=\"M8.25 4.5l7.5 7.5-7.5 7.5\"/>\n </svg>\n </a>\n `\n )\n .join(\"\")}\n </div>\n </div>\n </div>\n `;\n}\n\nfunction renderSystemStatus(): string {\n return `\n <div class=\"rounded-lg bg-white dark:bg-zinc-900 shadow-sm ring-1 ring-zinc-950/5 dark:ring-white/10 overflow-hidden\">\n <div class=\"border-b border-zinc-950/5 dark:border-white/10 px-6 py-6\">\n <div class=\"flex items-center justify-between\">\n <h3 class=\"text-base/7 font-semibold text-zinc-950 dark:text-white\">System Status</h3>\n <div class=\"flex items-center gap-2\">\n <div class=\"h-2 w-2 rounded-full bg-lime-500 animate-pulse\"></div>\n <span class=\"text-xs text-zinc-500 dark:text-zinc-400\">Live</span>\n </div>\n </div>\n </div>\n\n <div\n id=\"system-status-container\"\n class=\"p-6\"\n hx-get=\"/admin/dashboard/system-status\"\n hx-trigger=\"load, every 30s\"\n hx-swap=\"innerHTML\"\n >\n <!-- Loading skeleton with gradient -->\n <div class=\"grid grid-cols-1 sm:grid-cols-2 gap-4\">\n ${[\n { color: 'from-blue-500/20 to-cyan-500/20', darkColor: 'dark:from-blue-500/10 dark:to-cyan-500/10' },\n { color: 'from-purple-500/20 to-pink-500/20', darkColor: 'dark:from-purple-500/10 dark:to-pink-500/10' },\n { color: 'from-amber-500/20 to-orange-500/20', darkColor: 'dark:from-amber-500/10 dark:to-orange-500/10' },\n { color: 'from-lime-500/20 to-emerald-500/20', darkColor: 'dark:from-lime-500/10 dark:to-emerald-500/10' }\n ].map((gradient, i) => `\n <div class=\"relative group\">\n <div class=\"absolute inset-0 bg-gradient-to-br ${gradient.color} ${gradient.darkColor} rounded-xl opacity-0 group-hover:opacity-100 transition-opacity duration-300\"></div>\n <div class=\"relative bg-zinc-50 dark:bg-zinc-800/50 rounded-xl p-5 border border-zinc-200/50 dark:border-zinc-700/50 animate-pulse\">\n <div class=\"flex items-center justify-between mb-3\">\n <div class=\"h-4 w-24 bg-zinc-200 dark:bg-zinc-700 rounded\"></div>\n <div class=\"h-6 w-6 bg-zinc-200 dark:bg-zinc-700 rounded-full\"></div>\n </div>\n <div class=\"h-3 w-20 bg-zinc-200 dark:bg-zinc-700 rounded\"></div>\n </div>\n </div>\n `).join('')}\n </div>\n </div>\n </div>\n\n <style>\n @keyframes ping-slow {\n 0%, 100% { opacity: 1; }\n 50% { opacity: 0.5; }\n }\n .animate-ping-slow {\n animation: ping-slow 3s cubic-bezier(0.4, 0, 0.6, 1) infinite;\n }\n </style>\n `;\n}\n\nexport function renderStorageUsage(databaseSizeBytes?: number, mediaSizeBytes?: number): string {\n // Helper to format bytes to human readable\n const formatBytes = (bytes: number): string => {\n if (bytes === 0) return '0 B'\n const k = 1024\n const sizes = ['B', 'KB', 'MB', 'GB']\n const i = Math.floor(Math.log(bytes) / Math.log(k))\n return `${(bytes / Math.pow(k, i)).toFixed(2)} ${sizes[i]}`\n }\n\n const dbSizeGB = databaseSizeBytes ? databaseSizeBytes / (1024 ** 3) : 0\n const dbMaxGB = 10\n const dbPercentageRaw = (dbSizeGB / dbMaxGB) * 100\n // Ensure minimum 0.5% visibility for progress bar, max 100%\n const dbPercentage = Math.min(Math.max(dbPercentageRaw, 0.5), 100)\n const dbUsedFormatted = databaseSizeBytes ? formatBytes(databaseSizeBytes) : 'Unknown'\n\n const mediaUsedFormatted = mediaSizeBytes ? formatBytes(mediaSizeBytes) : '0 B'\n\n const storageItems = [\n {\n label: \"Database\",\n used: dbUsedFormatted,\n total: \"10 GB\",\n percentage: dbPercentage,\n color: dbPercentage > 80 ? \"bg-red-500 dark:bg-red-400\" : dbPercentage > 60 ? \"bg-amber-500 dark:bg-amber-400\" : \"bg-cyan-500 dark:bg-cyan-400\",\n },\n {\n label: \"Media Files\",\n used: mediaUsedFormatted,\n total: \"∞\",\n percentage: 0,\n color: \"bg-lime-500 dark:bg-lime-400\",\n note: \"Stored in R2\"\n },\n {\n label: \"Cache (KV)\",\n used: \"N/A\",\n total: \"∞\",\n percentage: 0,\n color: \"bg-purple-500 dark:bg-purple-400\",\n note: \"Unlimited\"\n },\n ];\n\n return `\n <div class=\"rounded-lg bg-white dark:bg-zinc-900 shadow-sm ring-1 ring-zinc-950/5 dark:ring-white/10\">\n <div class=\"border-b border-zinc-950/5 dark:border-white/10 px-6 py-6\">\n <h3 class=\"text-base/7 font-semibold text-zinc-950 dark:text-white\">Storage Usage</h3>\n </div>\n\n <div class=\"px-6 py-6\">\n <dl class=\"space-y-6\">\n ${storageItems\n .map(\n (item: any) => `\n <div>\n <div class=\"flex items-center justify-between mb-2\">\n <dt class=\"text-sm/6 text-zinc-500 dark:text-zinc-400\">\n ${item.label}\n ${item.note ? `<span class=\"ml-2 text-xs text-zinc-400 dark:text-zinc-500\">(${item.note})</span>` : ''}\n </dt>\n <dd class=\"text-sm/6 font-medium text-zinc-950 dark:text-white\">${item.used} / ${item.total}</dd>\n </div>\n <div class=\"w-full bg-zinc-100 dark:bg-zinc-800 rounded-full h-1.5 overflow-hidden\">\n <div class=\"${item.color} h-full rounded-full transition-all duration-300\" style=\"width: ${item.percentage}%\"></div>\n </div>\n </div>\n `\n )\n .join(\"\")}\n </dl>\n </div>\n </div>\n `;\n}","import { Hono } from 'hono'\nimport type { D1Database, KVNamespace, R2Bucket } from '@cloudflare/workers-types'\nimport { requireAuth } from '../middleware'\nimport {\n renderDashboardPage,\n type DashboardPageData,\n renderStatsCards,\n renderStorageUsage,\n renderRecentActivity,\n type ActivityItem\n} from '../templates/pages/admin-dashboard.template'\nimport { getCoreVersion } from '../utils/version'\nimport { metricsTracker } from '../utils/metrics'\n\nconst VERSION = getCoreVersion()\n\ntype Bindings = {\n DB: D1Database\n CACHE_KV: KVNamespace\n MEDIA_BUCKET: R2Bucket\n}\n\ntype Variables = {\n user?: {\n userId: string\n email: string\n role: string\n }\n}\n\nconst router = new Hono<{ Bindings: Bindings; Variables: Variables }>()\n\n// Apply authentication middleware\nrouter.use('*', requireAuth())\n\n/**\n * GET /admin - Admin Dashboard\n */\nrouter.get('/', async (c) => {\n const user = c.get('user')\n\n try {\n const pageData: DashboardPageData = {\n user: {\n name: user!.email.split('@')[0] || user!.email,\n email: user!.email,\n role: user!.role\n },\n version: VERSION\n }\n\n return c.html(renderDashboardPage(pageData))\n } catch (error) {\n console.error('Dashboard error:', error)\n\n // Return dashboard with error state\n const pageData: DashboardPageData = {\n user: {\n name: user!.email,\n email: user!.email,\n role: user!.role\n },\n version: VERSION\n }\n\n return c.html(renderDashboardPage(pageData))\n }\n})\n\n/**\n * GET /admin/dashboard/stats - Dashboard stats HTML fragment (HTMX endpoint)\n */\nrouter.get('/stats', async (c) => {\n try {\n const db = c.env.DB\n\n // Get collections count\n let collectionsCount = 0\n try {\n const collectionsStmt = db.prepare('SELECT COUNT(*) as count FROM collections WHERE is_active = 1')\n const collectionsResult = await collectionsStmt.first()\n collectionsCount = (collectionsResult as any)?.count || 0\n } catch (error) {\n console.error('Error fetching collections count:', error)\n }\n\n // Get content count\n let contentCount = 0\n try {\n const contentStmt = db.prepare('SELECT COUNT(*) as count FROM content')\n const contentResult = await contentStmt.first()\n contentCount = (contentResult as any)?.count || 0\n } catch (error) {\n console.error('Error fetching content count:', error)\n }\n\n // Get media count and total size\n let mediaCount = 0\n let mediaSize = 0\n try {\n const mediaStmt = db.prepare('SELECT COUNT(*) as count, COALESCE(SUM(size), 0) as total_size FROM media WHERE deleted_at IS NULL')\n const mediaResult = await mediaStmt.first()\n mediaCount = (mediaResult as any)?.count || 0\n mediaSize = (mediaResult as any)?.total_size || 0\n } catch (error) {\n console.error('Error fetching media count:', error)\n }\n\n // Get users count\n let usersCount = 0\n try {\n const usersStmt = db.prepare('SELECT COUNT(*) as count FROM users WHERE is_active = 1')\n const usersResult = await usersStmt.first()\n usersCount = (usersResult as any)?.count || 0\n } catch (error) {\n console.error('Error fetching users count:', error)\n }\n\n const html = renderStatsCards({\n collections: collectionsCount,\n contentItems: contentCount,\n mediaFiles: mediaCount,\n users: usersCount,\n mediaSize: mediaSize\n })\n\n return c.html(html)\n } catch (error) {\n console.error('Error fetching stats:', error)\n return c.html('<div class=\"text-red-500\">Failed to load statistics</div>')\n }\n})\n\n/**\n * GET /admin/dashboard/storage - Storage usage HTML fragment (HTMX endpoint)\n */\nrouter.get('/storage', async (c) => {\n try {\n const db = c.env.DB\n\n // Get database size from D1 metadata\n let databaseSize = 0\n try {\n const result = await db.prepare('SELECT 1').run()\n databaseSize = (result as any)?.meta?.size_after || 0\n } catch (error) {\n console.error('Error fetching database size:', error)\n }\n\n // Get media total size\n let mediaSize = 0\n try {\n const mediaStmt = db.prepare('SELECT COALESCE(SUM(size), 0) as total_size FROM media WHERE deleted_at IS NULL')\n const mediaResult = await mediaStmt.first()\n mediaSize = (mediaResult as any)?.total_size || 0\n } catch (error) {\n console.error('Error fetching media size:', error)\n }\n\n const html = renderStorageUsage(databaseSize, mediaSize)\n return c.html(html)\n } catch (error) {\n console.error('Error fetching storage usage:', error)\n return c.html('<div class=\"text-red-500\">Failed to load storage information</div>')\n }\n})\n\n/**\n * GET /admin/dashboard/recent-activity - Recent activity HTML fragment (HTMX endpoint)\n */\nrouter.get('/recent-activity', async (c) => {\n try {\n const db = c.env.DB\n const limit = parseInt(c.req.query('limit') || '5')\n\n // Get recent activities from activity_logs table\n const activityStmt = db.prepare(`\n SELECT\n a.id,\n a.action,\n a.resource_type,\n a.resource_id,\n a.details,\n a.created_at,\n u.email,\n u.first_name,\n u.last_name\n FROM activity_logs a\n LEFT JOIN users u ON a.user_id = u.id\n WHERE a.resource_type IN ('content', 'collections', 'users', 'media')\n ORDER BY a.created_at DESC\n LIMIT ?\n `)\n\n const { results } = await activityStmt.bind(limit).all()\n\n const activities: ActivityItem[] = (results || []).map((row: any) => {\n const userName = row.first_name && row.last_name\n ? `${row.first_name} ${row.last_name}`\n : row.email || 'System'\n\n // Format description based on action and resource type\n let description = ''\n if (row.action === 'create') {\n description = `Created new ${row.resource_type}`\n } else if (row.action === 'update') {\n description = `Updated ${row.resource_type}`\n } else if (row.action === 'delete') {\n description = `Deleted ${row.resource_type}`\n } else {\n description = `${row.action} ${row.resource_type}`\n }\n\n return {\n id: row.id,\n type: row.resource_type,\n action: row.action,\n description,\n timestamp: new Date(Number(row.created_at)).toISOString(),\n user: userName\n }\n })\n\n const html = renderRecentActivity(activities)\n return c.html(html)\n } catch (error) {\n console.error('Error fetching recent activity:', error)\n const html = renderRecentActivity([])\n return c.html(html)\n }\n})\n\n/**\n * GET /admin/api/metrics - Real-time metrics for analytics chart\n * Returns JSON with current requests per second from the metrics tracker\n */\nrouter.get('/api/metrics', async (c) => {\n return c.json({\n requestsPerSecond: metricsTracker.getRequestsPerSecond(),\n totalRequests: metricsTracker.getTotalRequests(),\n averageRPS: Number(metricsTracker.getAverageRPS().toFixed(2)),\n timestamp: new Date().toISOString()\n })\n})\n\n/**\n * GET /admin/dashboard/system-status - System status HTML fragment (HTMX endpoint)\n */\nrouter.get('/system-status', async (c) => {\n try {\n const html = `\n <div class=\"grid grid-cols-1 sm:grid-cols-2 gap-4\">\n <div class=\"relative group\">\n <div class=\"absolute inset-0 bg-gradient-to-br from-blue-500/20 to-cyan-500/20 dark:from-blue-500/10 dark:to-cyan-500/10 rounded-xl opacity-0 group-hover:opacity-100 transition-opacity duration-300\"></div>\n <div class=\"relative bg-zinc-50 dark:bg-zinc-800/50 rounded-xl p-5 border border-zinc-200/50 dark:border-zinc-700/50\">\n <div class=\"flex items-center justify-between mb-3\">\n <span class=\"text-sm font-medium text-zinc-600 dark:text-zinc-400\">API Status</span>\n <svg class=\"w-6 h-6 text-lime-500\" fill=\"currentColor\" viewBox=\"0 0 20 20\">\n <path fill-rule=\"evenodd\" d=\"M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z\" clip-rule=\"evenodd\"/>\n </svg>\n </div>\n <p class=\"text-xs text-zinc-500 dark:text-zinc-400\">Operational</p>\n </div>\n </div>\n\n <div class=\"relative group\">\n <div class=\"absolute inset-0 bg-gradient-to-br from-purple-500/20 to-pink-500/20 dark:from-purple-500/10 dark:to-pink-500/10 rounded-xl opacity-0 group-hover:opacity-100 transition-opacity duration-300\"></div>\n <div class=\"relative bg-zinc-50 dark:bg-zinc-800/50 rounded-xl p-5 border border-zinc-200/50 dark:border-zinc-700/50\">\n <div class=\"flex items-center justify-between mb-3\">\n <span class=\"text-sm font-medium text-zinc-600 dark:text-zinc-400\">Database</span>\n <svg class=\"w-6 h-6 text-lime-500\" fill=\"currentColor\" viewBox=\"0 0 20 20\">\n <path fill-rule=\"evenodd\" d=\"M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z\" clip-rule=\"evenodd\"/>\n </svg>\n </div>\n <p class=\"text-xs text-zinc-500 dark:text-zinc-400\">Connected</p>\n </div>\n </div>\n\n <div class=\"relative group\">\n <div class=\"absolute inset-0 bg-gradient-to-br from-amber-500/20 to-orange-500/20 dark:from-amber-500/10 dark:to-orange-500/10 rounded-xl opacity-0 group-hover:opacity-100 transition-opacity duration-300\"></div>\n <div class=\"relative bg-zinc-50 dark:bg-zinc-800/50 rounded-xl p-5 border border-zinc-200/50 dark:border-zinc-700/50\">\n <div class=\"flex items-center justify-between mb-3\">\n <span class=\"text-sm font-medium text-zinc-600 dark:text-zinc-400\">R2 Storage</span>\n <svg class=\"w-6 h-6 text-lime-500\" fill=\"currentColor\" viewBox=\"0 0 20 20\">\n <path fill-rule=\"evenodd\" d=\"M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z\" clip-rule=\"evenodd\"/>\n </svg>\n </div>\n <p class=\"text-xs text-zinc-500 dark:text-zinc-400\">Available</p>\n </div>\n </div>\n\n <div class=\"relative group\">\n <div class=\"absolute inset-0 bg-gradient-to-br from-lime-500/20 to-emerald-500/20 dark:from-lime-500/10 dark:to-emerald-500/10 rounded-xl opacity-0 group-hover:opacity-100 transition-opacity duration-300\"></div>\n <div class=\"relative bg-zinc-50 dark:bg-zinc-800/50 rounded-xl p-5 border border-zinc-200/50 dark:border-zinc-700/50\">\n <div class=\"flex items-center justify-between mb-3\">\n <span class=\"text-sm font-medium text-zinc-600 dark:text-zinc-400\">KV Cache</span>\n <svg class=\"w-6 h-6 text-lime-500\" fill=\"currentColor\" viewBox=\"0 0 20 20\">\n <path fill-rule=\"evenodd\" d=\"M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z\" clip-rule=\"evenodd\"/>\n </svg>\n </div>\n <p class=\"text-xs text-zinc-500 dark:text-zinc-400\">Ready</p>\n </div>\n </div>\n </div>\n `\n return c.html(html)\n } catch (error) {\n console.error('Error fetching system status:', error)\n return c.html('<div class=\"text-red-500\">Failed to load system status</div>')\n }\n})\n\nexport { router as adminDashboardRoutes }\n","import { renderAdminLayoutCatalyst, AdminLayoutCatalystData } from '../layouts/admin-layout-catalyst.template'\nimport { renderTable } from '../components/table.template'\n\nexport interface Collection {\n id: string\n name: string\n display_name: string\n description?: string\n created_at: number\n formattedDate: string\n field_count?: number\n managed?: boolean\n}\n\nexport interface CollectionsListPageData {\n collections: Collection[]\n search?: string\n user?: {\n name: string\n email: string\n role: string\n }\n version?: string\n}\n\nexport function renderCollectionsListPage(data: CollectionsListPageData): string {\n const tableData: any = {\n tableId: 'collections-table',\n rowClickable: true,\n rowClickUrl: (collection: Collection) => `/admin/collections/${collection.id}`,\n columns: [\n {\n key: 'name',\n label: 'Name',\n sortable: true,\n sortType: 'string',\n render: (_value: any, collection: any) => `\n <div class=\"flex items-center gap-2 ml-2\">\n <span class=\"inline-flex items-center rounded-md bg-cyan-50 dark:bg-cyan-500/10 px-2.5 py-1 text-sm font-medium text-cyan-700 dark:text-cyan-300 ring-1 ring-inset ring-cyan-700/10 dark:ring-cyan-400/20\">\n ${collection.name}\n </span>\n ${collection.managed ? `\n <span class=\"inline-flex items-center rounded-md bg-purple-50 dark:bg-purple-500/10 px-2 py-0.5 text-xs font-medium text-purple-700 dark:text-purple-300 ring-1 ring-inset ring-purple-700/10 dark:ring-purple-400/20\" title=\"Config-managed collection (read-only in UI)\">\n <svg class=\"w-3 h-3 mr-1\" fill=\"currentColor\" viewBox=\"0 0 20 20\">\n <path fill-rule=\"evenodd\" d=\"M5 9V7a5 5 0 0110 0v2a2 2 0 012 2v5a2 2 0 01-2 2H5a2 2 0 01-2-2v-5a2 2 0 012-2zm8-2v2H7V7a3 3 0 016 0z\" clip-rule=\"evenodd\"/>\n </svg>\n Config\n </span>\n ` : ''}\n </div>\n `\n },\n {\n key: 'display_name',\n label: 'Display Name',\n sortable: true,\n sortType: 'string'\n },\n {\n key: 'description',\n label: 'Description',\n sortable: true,\n sortType: 'string',\n render: (_value: any, collection: any) => collection.description || '<span class=\"text-zinc-500 dark:text-zinc-400\">-</span>'\n },\n {\n key: 'field_count',\n label: 'Fields',\n sortable: true,\n sortType: 'number',\n render: (_value: any, collection: any) => {\n const count = collection.field_count || 0\n return `\n <div class=\"flex items-center\">\n <span class=\"inline-flex items-center rounded-md bg-pink-50 dark:bg-pink-500/10 px-2.5 py-1 text-sm font-medium text-pink-700 dark:text-pink-300 ring-1 ring-inset ring-pink-700/10 dark:ring-pink-400/20\">\n ${count} ${count === 1 ? 'field' : 'fields'}\n </span>\n </div>\n `\n }\n },\n {\n key: 'managed',\n label: 'Source',\n sortable: true,\n sortType: 'string',\n render: (_value: any, collection: any) => {\n if (collection.managed) {\n return `\n <div class=\"flex items-center gap-1.5\">\n <svg class=\"w-4 h-4 text-purple-600 dark:text-purple-400\" fill=\"currentColor\" viewBox=\"0 0 20 20\">\n <path fill-rule=\"evenodd\" d=\"M12.316 3.051a1 1 0 01.633 1.265l-4 12a1 1 0 11-1.898-.632l4-12a1 1 0 011.265-.633zM5.707 6.293a1 1 0 010 1.414L3.414 10l2.293 2.293a1 1 0 11-1.414 1.414l-3-3a1 1 0 010-1.414l3-3a1 1 0 011.414 0zm8.586 0a1 1 0 011.414 0l3 3a1 1 0 010 1.414l-3 3a1 1 0 11-1.414-1.414L16.586 10l-2.293-2.293a1 1 0 010-1.414z\" clip-rule=\"evenodd\"/>\n </svg>\n <span class=\"text-sm text-zinc-700 dark:text-zinc-300\">Code</span>\n </div>\n `\n } else {\n return `\n <div class=\"flex items-center gap-1.5\">\n <svg class=\"w-4 h-4 text-blue-600 dark:text-blue-400\" fill=\"currentColor\" viewBox=\"0 0 20 20\">\n <path d=\"M3 12v3c0 1.657 3.134 3 7 3s7-1.343 7-3v-3c0 1.657-3.134 3-7 3s-7-1.343-7-3z\"/>\n <path d=\"M3 7v3c0 1.657 3.134 3 7 3s7-1.343 7-3V7c0 1.657-3.134 3-7 3S3 8.657 3 7z\"/>\n <path d=\"M17 5c0 1.657-3.134 3-7 3S3 6.657 3 5s3.134-3 7-3 7 1.343 7 3z\"/>\n </svg>\n <span class=\"text-sm text-zinc-700 dark:text-zinc-300\">Database</span>\n </div>\n `\n }\n }\n },\n {\n key: 'formattedDate',\n label: 'Created',\n sortable: true,\n sortType: 'date'\n },\n {\n key: 'actions',\n label: 'Content',\n sortable: false,\n render: (_value: any, collection: any) => {\n if (!collection || !collection.id) return '<span class=\"text-zinc-500 dark:text-zinc-400\">-</span>'\n return `\n <div class=\"flex items-center space-x-2\">\n <a href=\"/admin/content?model=${collection.name}\" class=\"inline-flex items-center px-3 py-1.5 text-sm font-medium rounded-lg bg-zinc-950 dark:bg-white text-white dark:text-zinc-950 hover:bg-zinc-800 dark:hover:bg-zinc-100 transition-colors\">\n <svg class=\"w-4 h-4\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z\"></path>\n </svg>\n </a>\n </div>\n `\n }\n }\n ],\n rows: data.collections,\n emptyMessage: 'No collections found.'\n }\n\n const pageContent = `\n <div>\n <!-- Header -->\n <div class=\"flex flex-col sm:flex-row sm:items-center sm:justify-between mb-6\">\n <div>\n <h1 class=\"text-2xl/8 font-semibold text-zinc-950 dark:text-white sm:text-xl/8\">Collections</h1>\n <p class=\"mt-2 text-sm/6 text-zinc-500 dark:text-zinc-400\">Manage your content collections and their schemas</p>\n </div>\n <div class=\"mt-4 sm:mt-0 sm:ml-16 sm:flex-none\">\n <a href=\"/admin/collections/new\" class=\"inline-flex items-center justify-center rounded-lg bg-zinc-950 dark:bg-white px-3.5 py-2.5 text-sm font-semibold text-white dark:text-zinc-950 hover:bg-zinc-800 dark:hover:bg-zinc-100 transition-colors shadow-sm\">\n <svg class=\"-ml-0.5 mr-1.5 h-5 w-5\" viewBox=\"0 0 20 20\" fill=\"currentColor\">\n <path d=\"M10.75 4.75a.75.75 0 00-1.5 0v4.5h-4.5a.75.75 0 000 1.5h4.5v4.5a.75.75 0 001.5 0v-4.5h4.5a.75.75 0 000-1.5h-4.5v-4.5z\" />\n </svg>\n New Collection\n </a>\n </div>\n </div>\n\n <!-- Filters -->\n <div class=\"relative rounded-xl overflow-hidden mb-6\">\n <!-- Gradient Background -->\n <div class=\"absolute inset-0 bg-gradient-to-r from-cyan-500/10 via-blue-500/10 to-purple-500/10 dark:from-cyan-400/20 dark:via-blue-400/20 dark:to-purple-400/20\"></div>\n\n <div class=\"relative bg-white/80 dark:bg-zinc-900/80 backdrop-blur-xl shadow-sm ring-1 ring-zinc-950/5 dark:ring-white/10\">\n <div class=\"px-6 py-5\">\n <div class=\"flex items-center justify-between\">\n <div class=\"flex items-center space-x-4\">\n <form onsubmit=\"performSearch(event)\" class=\"flex items-center space-x-2\">\n <div class=\"relative group\">\n <input\n id=\"collections-search\"\n type=\"text\"\n placeholder=\"Search collections...\"\n value=\"${data.search || ''}\"\n oninput=\"toggleClearButton()\"\n class=\"rounded-full bg-white/90 dark:bg-zinc-800/90 backdrop-blur-sm px-4 py-2.5 pl-11 pr-10 text-sm w-72 text-zinc-950 dark:text-white border-2 border-cyan-200/50 dark:border-cyan-700/50 placeholder:text-zinc-400 dark:placeholder:text-zinc-500 focus:outline-none focus:border-cyan-500 dark:focus:border-cyan-400 focus:bg-white dark:focus:bg-zinc-800 focus:shadow-lg focus:shadow-cyan-500/20 dark:focus:shadow-cyan-400/20 transition-all duration-300\"\n >\n <div class=\"absolute left-3.5 top-2.5 flex items-center justify-center w-5 h-5 rounded-full bg-gradient-to-br from-cyan-400 to-blue-500 dark:from-cyan-300 dark:to-blue-400 opacity-90 group-focus-within:opacity-100 transition-opacity\">\n <svg class=\"h-3 w-3 text-white\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\" stroke-width=\"2.5\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z\"/>\n </svg>\n </div>\n <button\n type=\"button\"\n id=\"clear-search\"\n onclick=\"clearSearch()\"\n class=\"${data.search ? '' : 'hidden'} absolute right-3 top-3 flex items-center justify-center w-5 h-5 rounded-full bg-zinc-400/20 dark:bg-zinc-500/20 hover:bg-zinc-400/30 dark:hover:bg-zinc-500/30 transition-colors\"\n >\n <svg class=\"h-3 w-3 text-zinc-600 dark:text-zinc-400\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\" stroke-width=\"2.5\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M6 18L18 6M6 6l12 12\"/>\n </svg>\n </button>\n </div>\n <button\n type=\"submit\"\n class=\"inline-flex items-center gap-x-1.5 px-4 py-2.5 bg-gradient-to-r from-cyan-500 to-blue-500 dark:from-cyan-400 dark:to-blue-400 text-white text-sm font-medium rounded-full hover:from-cyan-600 hover:to-blue-600 dark:hover:from-cyan-500 dark:hover:to-blue-500 shadow-md hover:shadow-lg transition-all duration-200\"\n >\n <svg class=\"h-4 w-4\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\" stroke-width=\"2.5\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z\"/>\n </svg>\n Search\n </button>\n </form>\n <script>\n function performSearch(event) {\n event.preventDefault();\n const searchInput = document.getElementById('collections-search');\n const value = searchInput.value.trim();\n const params = new URLSearchParams(window.location.search);\n if (value) {\n params.set('search', value);\n } else {\n params.delete('search');\n }\n window.location.href = window.location.pathname + '?' + params.toString();\n }\n\n function clearSearch() {\n const params = new URLSearchParams(window.location.search);\n params.delete('search');\n window.location.href = window.location.pathname + (params.toString() ? '?' + params.toString() : '');\n }\n\n function toggleClearButton() {\n const searchInput = document.getElementById('collections-search');\n const clearButton = document.getElementById('clear-search');\n if (searchInput.value.trim()) {\n clearButton.classList.remove('hidden');\n } else {\n clearButton.classList.add('hidden');\n }\n }\n </script>\n </div>\n <div class=\"flex items-center gap-x-3\">\n <span class=\"text-sm/6 font-medium text-zinc-700 dark:text-zinc-300 px-3 py-1.5 rounded-full bg-white/60 dark:bg-zinc-800/60 backdrop-blur-sm\">${data.collections.length} ${data.collections.length === 1 ? 'collection' : 'collections'}</span>\n <button\n class=\"inline-flex items-center gap-x-1.5 px-3 py-1.5 bg-white/90 dark:bg-zinc-800/90 backdrop-blur-sm text-zinc-950 dark:text-white text-sm font-medium rounded-full ring-1 ring-inset ring-cyan-200/50 dark:ring-cyan-700/50 hover:bg-gradient-to-r hover:from-cyan-50 hover:to-blue-50 dark:hover:from-cyan-900/30 dark:hover:to-blue-900/30 hover:ring-cyan-300 dark:hover:ring-cyan-600 transition-all duration-200\"\n onclick=\"location.reload()\"\n >\n <svg class=\"h-4 w-4\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15\"/>\n </svg>\n Refresh\n </button>\n </div>\n </div>\n </div>\n </div>\n </div>\n\n <!-- Collections List -->\n <div id=\"collections-list\">\n ${renderTable(tableData)}\n </div>\n\n <!-- Empty State -->\n ${data.collections.length === 0 ? `\n <div class=\"rounded-lg bg-white dark:bg-zinc-900 shadow-sm ring-1 ring-zinc-950/5 dark:ring-white/10 p-12 text-center\">\n <svg class=\"mx-auto h-12 w-12 text-zinc-400 dark:text-zinc-500\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"1.5\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M19 11H5m14 0a2 2 0 012 2v6a2 2 0 01-2 2H5a2 2 0 01-2-2v-6a2 2 0 012-2m14 0V9a2 2 0 00-2-2M5 11V9a2 2 0 012-2m0 0V5a2 2 0 012-2h6a2 2 0 012 2v2M7 7h10\"/>\n </svg>\n <h3 class=\"mt-4 text-base/7 font-semibold text-zinc-950 dark:text-white\">No collections found</h3>\n <p class=\"mt-2 text-sm/6 text-zinc-500 dark:text-zinc-400\">Get started by creating your first collection</p>\n <div class=\"mt-6\">\n <a href=\"/admin/collections/new\" class=\"inline-flex items-center justify-center rounded-lg bg-zinc-950 dark:bg-white px-3.5 py-2.5 text-sm font-semibold text-white dark:text-zinc-950 hover:bg-zinc-800 dark:hover:bg-zinc-100 transition-colors shadow-sm\">\n <svg class=\"-ml-0.5 mr-1.5 h-5 w-5\" viewBox=\"0 0 20 20\" fill=\"currentColor\">\n <path d=\"M10.75 4.75a.75.75 0 00-1.5 0v4.5h-4.5a.75.75 0 000 1.5h4.5v4.5a.75.75 0 001.5 0v-4.5h4.5a.75.75 0 000-1.5h-4.5v-4.5z\" />\n </svg>\n New Collection\n </a>\n </div>\n </div>\n ` : ''}\n </div>\n `\n\n const layoutData: AdminLayoutCatalystData = {\n title: 'Collections',\n pageTitle: 'Collections',\n currentPath: '/admin/collections',\n user: data.user,\n version: data.version,\n content: pageContent\n }\n\n return renderAdminLayoutCatalyst(layoutData)\n}","export interface TableColumn {\n key: string\n label: string\n sortable?: boolean\n className?: string\n sortType?: 'string' | 'number' | 'date' | 'boolean'\n render?: (value: any, row: any) => string\n}\n\nexport interface TableData<T = any> {\n columns: TableColumn[]\n rows: T[]\n selectable?: boolean\n className?: string\n emptyMessage?: string\n tableId?: string\n title?: string\n rowClickable?: boolean\n rowClickUrl?: (row: T) => string\n}\n\nexport function renderTable<T = any>(data: TableData<T>): string {\n const tableId = data.tableId || `table-${Math.random().toString(36).substr(2, 9)}`\n\n if (data.rows.length === 0) {\n return `\n <div class=\"rounded-xl bg-white dark:bg-zinc-900 shadow-sm ring-1 ring-zinc-950/5 dark:ring-white/10 p-8 text-center\">\n <div class=\"text-zinc-500 dark:text-zinc-400\">\n <svg class=\"mx-auto h-12 w-12 text-zinc-400 dark:text-zinc-500\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z\" />\n </svg>\n <p class=\"mt-2 text-sm text-zinc-500 dark:text-zinc-400\">${data.emptyMessage || 'No data available'}</p>\n </div>\n </div>\n `\n }\n\n return `\n <div class=\"${data.className || ''}\" id=\"${tableId}\">\n ${data.title ? `\n <div class=\"px-4 sm:px-0 mb-4\">\n <h3 class=\"text-base font-semibold text-zinc-950 dark:text-white\">${data.title}</h3>\n </div>\n ` : ''}\n <div class=\"overflow-x-auto\">\n <table class=\"min-w-full sortable-table\">\n <thead>\n <tr>\n ${data.selectable ? `\n <th class=\"px-4 py-3.5 text-center sm:pl-0\">\n <div class=\"flex items-center justify-center\">\n <div class=\"group grid size-4 grid-cols-1\">\n <input type=\"checkbox\" id=\"select-all-${tableId}\" class=\"col-start-1 row-start-1 appearance-none rounded border border-white/10 bg-white/5 checked:border-cyan-500 checked:bg-cyan-500 indeterminate:border-cyan-500 indeterminate:bg-cyan-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-cyan-500 disabled:border-white/5 disabled:bg-white/10 disabled:checked:bg-white/10 forced-colors:appearance-auto row-checkbox\" />\n <svg viewBox=\"0 0 14 14\" fill=\"none\" class=\"pointer-events-none col-start-1 row-start-1 size-3.5 self-center justify-self-center stroke-white group-has-[:disabled]:stroke-white/25\">\n <path d=\"M3 8L6 11L11 3.5\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"opacity-0 group-has-[:checked]:opacity-100\" />\n <path d=\"M3 7H11\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"opacity-0 group-has-[:indeterminate]:opacity-100\" />\n </svg>\n </div>\n </div>\n </th>\n ` : ''}\n ${data.columns.map((column, index) => {\n const isFirst = index === 0 && !data.selectable\n const isLast = index === data.columns.length - 1\n return `\n <th class=\"px-4 py-3.5 text-left text-sm font-semibold text-zinc-950 dark:text-white ${isFirst ? 'sm:pl-0' : ''} ${isLast ? 'sm:pr-0' : ''} ${column.className || ''}\">\n ${column.sortable ? `\n <button\n class=\"flex items-center gap-x-2 hover:text-zinc-700 dark:hover:text-zinc-300 transition-colors sort-btn text-left\"\n data-column=\"${column.key}\"\n data-sort-type=\"${column.sortType || 'string'}\"\n data-sort-direction=\"none\"\n onclick=\"sortTable('${tableId}', '${column.key}', '${column.sortType || 'string'}')\"\n >\n <span>${column.label}</span>\n <div class=\"sort-icons flex flex-col\">\n <svg class=\"w-3 h-3 sort-up opacity-30\" fill=\"currentColor\" viewBox=\"0 0 20 20\">\n <path fill-rule=\"evenodd\" d=\"M14.707 12.707a1 1 0 01-1.414 0L10 9.414l-3.293 3.293a1 1 0 01-1.414-1.414l4-4a1 1 0 011.414 0l4 4a1 1 0 010 1.414z\" clip-rule=\"evenodd\" />\n </svg>\n <svg class=\"w-3 h-3 sort-down opacity-30 -mt-1\" fill=\"currentColor\" viewBox=\"0 0 20 20\">\n <path fill-rule=\"evenodd\" d=\"M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z\" clip-rule=\"evenodd\" />\n </svg>\n </div>\n </button>\n ` : column.label}\n </th>\n `}).join('')}\n </tr>\n </thead>\n <tbody>\n ${data.rows.map((row, rowIndex) => {\n if (!row) return ''\n const clickableClass = data.rowClickable ? 'cursor-pointer' : ''\n const clickHandler = data.rowClickable && data.rowClickUrl ? `onclick=\"window.location.href='${data.rowClickUrl(row)}'\"` : ''\n return `\n <tr class=\"group border-t border-zinc-950/5 dark:border-white/5 hover:bg-gradient-to-r hover:from-cyan-50/50 hover:via-blue-50/30 hover:to-purple-50/50 dark:hover:from-cyan-900/20 dark:hover:via-blue-900/10 dark:hover:to-purple-900/20 hover:shadow-sm hover:shadow-cyan-500/5 dark:hover:shadow-cyan-400/5 transition-all duration-300 ${clickableClass}\" ${clickHandler}>\n ${data.selectable ? `\n <td class=\"px-4 py-4 sm:pl-0\" onclick=\"event.stopPropagation()\">\n <div class=\"flex items-center justify-center\">\n <div class=\"group grid size-4 grid-cols-1\">\n <input type=\"checkbox\" value=\"${(row as any).id || ''}\" class=\"col-start-1 row-start-1 appearance-none rounded border border-white/10 bg-white/5 checked:border-cyan-500 checked:bg-cyan-500 indeterminate:border-cyan-500 indeterminate:bg-cyan-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-cyan-500 disabled:border-white/5 disabled:bg-white/10 disabled:checked:bg-white/10 forced-colors:appearance-auto row-checkbox\" />\n <svg viewBox=\"0 0 14 14\" fill=\"none\" class=\"pointer-events-none col-start-1 row-start-1 size-3.5 self-center justify-self-center stroke-white group-has-[:disabled]:stroke-white/25\">\n <path d=\"M3 8L6 11L11 3.5\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"opacity-0 group-has-[:checked]:opacity-100\" />\n <path d=\"M3 7H11\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"opacity-0 group-has-[:indeterminate]:opacity-100\" />\n </svg>\n </div>\n </div>\n </td>\n ` : ''}\n ${data.columns.map((column, colIndex) => {\n const value = (row as any)[column.key]\n const displayValue = column.render ? column.render(value, row) : value\n const stopPropagation = column.key === 'actions' ? 'onclick=\"event.stopPropagation()\"' : ''\n const isFirst = colIndex === 0 && !data.selectable\n const isLast = colIndex === data.columns.length - 1\n return `\n <td class=\"px-4 py-4 text-sm text-zinc-500 dark:text-zinc-400 ${isFirst ? 'sm:pl-0 font-medium text-zinc-950 dark:text-white' : ''} ${isLast ? 'sm:pr-0' : ''} ${column.className || ''}\" ${stopPropagation}>\n ${displayValue || ''}\n </td>\n `\n }).join('')}\n </tr>\n `\n }).join('')}\n </tbody>\n </table>\n </div>\n\n <script>\n // Table sorting functionality\n window.sortTable = function(tableId, column, sortType) {\n const tableContainer = document.getElementById(tableId);\n const table = tableContainer.querySelector('.sortable-table');\n const tbody = table.querySelector('tbody');\n const rows = Array.from(tbody.querySelectorAll('tr'));\n const headerBtn = table.querySelector(\\`[data-column=\"\\${column}\"]\\`);\n\n // Get current sort direction\n let direction = headerBtn.getAttribute('data-sort-direction');\n\n // Reset all sort indicators\n table.querySelectorAll('.sort-btn').forEach(btn => {\n btn.setAttribute('data-sort-direction', 'none');\n btn.querySelectorAll('.sort-up, .sort-down').forEach(icon => {\n icon.classList.add('opacity-30');\n icon.classList.remove('opacity-100', 'text-zinc-950', 'dark:text-white');\n });\n });\n\n // Determine new direction\n if (direction === 'none' || direction === 'desc') {\n direction = 'asc';\n } else {\n direction = 'desc';\n }\n\n // Update current header\n headerBtn.setAttribute('data-sort-direction', direction);\n const upIcon = headerBtn.querySelector('.sort-up');\n const downIcon = headerBtn.querySelector('.sort-down');\n\n if (direction === 'asc') {\n upIcon.classList.remove('opacity-30');\n upIcon.classList.add('opacity-100', 'text-zinc-950', 'dark:text-white');\n downIcon.classList.add('opacity-30');\n downIcon.classList.remove('opacity-100', 'text-zinc-950', 'dark:text-white');\n } else {\n downIcon.classList.remove('opacity-30');\n downIcon.classList.add('opacity-100', 'text-zinc-950', 'dark:text-white');\n upIcon.classList.add('opacity-30');\n upIcon.classList.remove('opacity-100', 'text-zinc-950', 'dark:text-white');\n }\n\n // Find column index (accounting for potential select column)\n const headers = Array.from(table.querySelectorAll('th'));\n const selectableOffset = table.querySelector('input[id^=\"select-all\"]') ? 1 : 0;\n const columnIndex = headers.findIndex(th => th.querySelector(\\`[data-column=\"\\${column}\"]\\`)) - selectableOffset;\n\n // Sort rows\n rows.sort((a, b) => {\n const aCell = a.children[columnIndex + selectableOffset];\n const bCell = b.children[columnIndex + selectableOffset];\n\n if (!aCell || !bCell) return 0;\n\n let aValue = aCell.textContent.trim();\n let bValue = bCell.textContent.trim();\n\n // Handle different sort types\n switch (sortType) {\n case 'number':\n aValue = parseFloat(aValue.replace(/[^0-9.-]/g, '')) || 0;\n bValue = parseFloat(bValue.replace(/[^0-9.-]/g, '')) || 0;\n break;\n case 'date':\n aValue = new Date(aValue).getTime() || 0;\n bValue = new Date(bValue).getTime() || 0;\n break;\n case 'boolean':\n aValue = aValue.toLowerCase() === 'true' || aValue.toLowerCase() === 'published' || aValue.toLowerCase() === 'active';\n bValue = bValue.toLowerCase() === 'true' || bValue.toLowerCase() === 'published' || bValue.toLowerCase() === 'active';\n break;\n default: // string\n aValue = aValue.toLowerCase();\n bValue = bValue.toLowerCase();\n }\n\n if (aValue < bValue) return direction === 'asc' ? -1 : 1;\n if (aValue > bValue) return direction === 'asc' ? 1 : -1;\n return 0;\n });\n\n // Re-append sorted rows\n rows.forEach(row => tbody.appendChild(row));\n };\n\n // Select all functionality\n document.addEventListener('DOMContentLoaded', function() {\n document.querySelectorAll('[id^=\"select-all\"]').forEach(selectAll => {\n selectAll.addEventListener('change', function() {\n const tableId = this.id.replace('select-all-', '');\n const table = document.getElementById(tableId);\n if (table) {\n const checkboxes = table.querySelectorAll('.row-checkbox');\n checkboxes.forEach(checkbox => {\n checkbox.checked = this.checked;\n });\n }\n });\n });\n });\n </script>\n </div>\n `\n}","import { renderAdminLayoutCatalyst, AdminLayoutCatalystData } from '../layouts/admin-layout-catalyst.template'\nimport { renderForm, FormData, FormField } from '../form.template'\nimport { renderAlert } from '../components/alert.template'\nimport { renderConfirmationDialog, getConfirmationDialogScript } from '../components/confirmation-dialog.template'\n\nexport interface CollectionField {\n id: string\n field_name: string\n field_type: string\n field_label: string\n field_options: any\n field_order: number\n is_required: boolean\n is_searchable: boolean\n}\n\nexport interface CollectionFormData {\n id?: string\n name?: string\n display_name?: string\n description?: string\n fields?: CollectionField[]\n managed?: boolean\n isEdit?: boolean\n error?: string\n success?: string\n user?: {\n name: string\n email: string\n role: string\n }\n version?: string\n editorPlugins?: {\n tinymce: boolean\n quill: boolean\n easyMdx: boolean\n }\n}\n\n// Helper function to get field type badge with color\nfunction getFieldTypeBadge(fieldType: string): string {\n const typeLabels: Record<string, string> = {\n 'text': 'Text',\n 'richtext': 'Rich Text (TinyMCE)',\n 'quill': 'Rich Text (Quill)',\n 'mdxeditor': 'EasyMDX',\n 'number': 'Number',\n 'boolean': 'Boolean',\n 'date': 'Date',\n 'select': 'Select',\n 'media': 'Media'\n }\n const typeColors: Record<string, string> = {\n 'text': 'bg-blue-500/10 dark:bg-blue-400/10 text-blue-700 dark:text-blue-300 ring-blue-500/20 dark:ring-blue-400/20',\n 'richtext': 'bg-purple-500/10 dark:bg-purple-400/10 text-purple-700 dark:text-purple-300 ring-purple-500/20 dark:ring-purple-400/20',\n 'quill': 'bg-purple-500/10 dark:bg-purple-400/10 text-purple-700 dark:text-purple-300 ring-purple-500/20 dark:ring-purple-400/20',\n 'mdxeditor': 'bg-purple-500/10 dark:bg-purple-400/10 text-purple-700 dark:text-purple-300 ring-purple-500/20 dark:ring-purple-400/20',\n 'number': 'bg-green-500/10 dark:bg-green-400/10 text-green-700 dark:text-green-300 ring-green-500/20 dark:ring-green-400/20',\n 'boolean': 'bg-amber-500/10 dark:bg-amber-400/10 text-amber-700 dark:text-amber-300 ring-amber-500/20 dark:ring-amber-400/20',\n 'date': 'bg-cyan-500/10 dark:bg-cyan-400/10 text-cyan-700 dark:text-cyan-300 ring-cyan-500/20 dark:ring-cyan-400/20',\n 'select': 'bg-indigo-500/10 dark:bg-indigo-400/10 text-indigo-700 dark:text-indigo-300 ring-indigo-500/20 dark:ring-indigo-400/20',\n 'media': 'bg-rose-500/10 dark:bg-rose-400/10 text-rose-700 dark:text-rose-300 ring-rose-500/20 dark:ring-rose-400/20'\n }\n const label = typeLabels[fieldType] || fieldType\n const color = typeColors[fieldType] || 'bg-zinc-500/10 dark:bg-zinc-400/10 text-zinc-700 dark:text-zinc-300 ring-zinc-500/20 dark:ring-zinc-400/20'\n return `<span class=\"inline-flex items-center rounded-md px-2 py-1 text-xs font-medium ${color} ring-1 ring-inset\">${label}</span>`\n}\n\nexport function renderCollectionFormPage(data: CollectionFormData): string {\n console.log('[renderCollectionFormPage] editorPlugins:', data.editorPlugins)\n\n const isEdit = data.isEdit || !!data.id\n const title = isEdit ? 'Edit Collection' : 'Create New Collection'\n const subtitle = isEdit\n ? `Update collection: ${data.display_name}`\n : 'Define a new content collection with custom fields and settings.'\n\n // Pre-compute data attribute for all fields (without badge HTML to avoid escaping issues)\n const fieldsWithData = (data.fields || []).map(field => ({\n ...field,\n dataFieldJSON: JSON.stringify(JSON.stringify(field))\n }))\n\n const fields: FormField[] = [\n {\n name: 'displayName',\n label: 'Display Name',\n type: 'text',\n value: data.display_name || '',\n placeholder: 'Blog Posts',\n required: true,\n readonly: data.managed,\n className: data.managed ? 'bg-zinc-100 dark:bg-zinc-800 text-zinc-500 dark:text-zinc-400 cursor-not-allowed' : ''\n },\n {\n name: 'name',\n label: 'Collection Name',\n type: 'text',\n value: data.name || '',\n placeholder: 'blog_posts',\n required: true,\n readonly: isEdit,\n helpText: isEdit ? 'Collection name cannot be changed' : 'Lowercase letters, numbers, and underscores only',\n className: isEdit ? 'bg-zinc-100 dark:bg-zinc-800 text-zinc-500 dark:text-zinc-400 cursor-not-allowed' : ''\n },\n {\n name: 'description',\n label: 'Description',\n type: 'textarea',\n value: data.description || '',\n placeholder: 'Description of this collection...',\n rows: 3,\n readonly: data.managed,\n className: data.managed ? 'bg-zinc-100 dark:bg-zinc-800 text-zinc-500 dark:text-zinc-400 cursor-not-allowed' : ''\n }\n ]\n\n\n const formData: FormData = {\n id: 'collection-form',\n ...(isEdit\n ? { hxPut: `/admin/collections/${data.id}`, action: `/admin/collections/${data.id}`, method: 'PUT' }\n : { hxPost: '/admin/collections', action: '/admin/collections' }\n ),\n hxTarget: '#form-messages',\n fields: fields,\n submitButtons: data.managed ? [] : [\n {\n label: isEdit ? 'Update Collection' : 'Create Collection',\n type: 'submit',\n className: 'btn-primary'\n }\n ]\n }\n\n const pageContent = `\n <div class=\"space-y-6\">\n <!-- Config-Managed Collection Banner -->\n ${data.managed ? `\n <div class=\"rounded-lg bg-amber-50 dark:bg-amber-900/20 border border-amber-200 dark:border-amber-900/30 p-4\">\n <div class=\"flex items-start gap-x-3\">\n <svg class=\"h-5 w-5 text-amber-600 dark:text-amber-400 mt-0.5\" fill=\"currentColor\" viewBox=\"0 0 20 20\">\n <path fill-rule=\"evenodd\" d=\"M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7-4a1 1 0 11-2 0 1 1 0 012 0zM9 9a1 1 0 000 2v3a1 1 0 001 1h1a1 1 0 100-2v-3a1 1 0 00-1-1H9z\" clip-rule=\"evenodd\"/>\n </svg>\n <div class=\"flex-1\">\n <h3 class=\"text-sm/6 font-semibold text-amber-900 dark:text-amber-300\">\n Config-Managed Collection\n </h3>\n <div class=\"text-sm/6 text-amber-800 dark:text-amber-400 mt-1 space-y-1\">\n <p>This collection is managed by a configuration file and cannot be edited through the admin interface.</p>\n <p class=\"mt-2\">\n <span class=\"font-medium\">Config file:</span>\n <code class=\"ml-2 px-2 py-0.5 rounded bg-amber-100 dark:bg-amber-900/40 text-amber-900 dark:text-amber-300 font-mono text-xs\">\n src/collections/${data.name}.collection.ts\n </code>\n </p>\n <p class=\"mt-2 text-xs\">\n To modify this collection's schema, edit the configuration file directly in your code editor.\n </p>\n </div>\n </div>\n </div>\n </div>\n ` : ''}\n\n <!-- Header -->\n <div class=\"flex flex-col sm:flex-row sm:items-center sm:justify-between\">\n <div>\n <h1 class=\"text-2xl/8 font-semibold text-zinc-950 dark:text-white sm:text-xl/8\">${title}</h1>\n <p class=\"mt-2 text-sm/6 text-zinc-500 dark:text-zinc-400\">${subtitle}</p>\n </div>\n <div class=\"mt-4 sm:mt-0 sm:ml-16 sm:flex-none\">\n <a href=\"/admin/collections\" class=\"inline-flex items-center justify-center rounded-lg bg-white dark:bg-zinc-800 px-3.5 py-2.5 text-sm font-semibold text-zinc-950 dark:text-white ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 hover:bg-zinc-50 dark:hover:bg-zinc-700 transition-colors shadow-sm\">\n <svg class=\"-ml-0.5 mr-1.5 h-5 w-5\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M10 19l-7-7m0 0l7-7m-7 7h18\"/>\n </svg>\n Back to Collections\n </a>\n </div>\n </div>\n\n <!-- Form Container -->\n <div class=\"rounded-lg bg-white dark:bg-zinc-900 shadow-sm ring-1 ring-zinc-950/5 dark:ring-white/10 overflow-hidden\">\n <!-- Form Header -->\n <div class=\"border-b border-zinc-950/5 dark:border-white/10 px-6 py-6\">\n <div class=\"flex items-center gap-x-3\">\n <div class=\"flex h-12 w-12 items-center justify-center rounded-lg bg-zinc-50 dark:bg-zinc-800 ring-1 ring-zinc-950/10 dark:ring-white/10\">\n <svg class=\"h-6 w-6 text-zinc-950 dark:text-white\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\" stroke-width=\"1.5\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M19 11H5m14 0a2 2 0 012 2v6a2 2 0 01-2 2H5a2 2 0 01-2-2v-6a2 2 0 012-2m14 0V9a2 2 0 00-2-2M5 11V9a2 2 0 012-2m0 0V5a2 2 0 012-2h6a2 2 0 012 2v2M7 7h10\"/>\n </svg>\n </div>\n <div>\n <h2 class=\"text-base/7 font-semibold text-zinc-950 dark:text-white\">Collection Details</h2>\n <p class=\"text-sm/6 text-zinc-500 dark:text-zinc-400\">Configure your collection settings below</p>\n </div>\n </div>\n </div>\n\n <!-- Form Content -->\n <div class=\"px-6 py-6\">\n <div id=\"form-messages\"></div>\n ${data.error ? renderAlert({ type: 'error', message: data.error, dismissible: true }) : ''}\n ${data.success ? renderAlert({ type: 'success', message: data.success, dismissible: true }) : ''}\n\n <!-- Form Styling -->\n <style>\n #collection-form .form-group {\n margin-bottom: 1.5rem;\n }\n\n #collection-form .form-label {\n display: block;\n font-size: 0.875rem;\n font-weight: 500;\n margin-bottom: 0.5rem;\n line-height: 1.5rem;\n }\n\n .dark #collection-form .form-label {\n color: white;\n }\n\n html:not(.dark) #collection-form .form-label {\n color: #09090b; /* zinc-950 */\n }\n\n #collection-form .form-input,\n #collection-form .form-textarea {\n width: 100%;\n padding: 0.625rem 0.75rem;\n border-radius: 0.5rem;\n font-size: 0.875rem;\n line-height: 1.5rem;\n transition: all 0.15s;\n }\n\n html:not(.dark) #collection-form .form-input,\n html:not(.dark) #collection-form .form-textarea {\n background: white;\n border: 1px solid rgba(9, 9, 11, 0.1); /* zinc-950/10 */\n color: #09090b; /* zinc-950 */\n }\n\n .dark #collection-form .form-input,\n .dark #collection-form .form-textarea {\n background: #18181b; /* zinc-900 */\n border: 1px solid rgba(255, 255, 255, 0.1);\n color: white;\n }\n\n #collection-form .form-input:focus,\n #collection-form .form-textarea:focus {\n outline: none;\n box-shadow: 0 0 0 2px #2563eb; /* blue-600 */\n }\n\n .dark #collection-form .form-input:focus,\n .dark #collection-form .form-textarea:focus {\n box-shadow: 0 0 0 2px #3b82f6; /* blue-500 */\n }\n\n html:not(.dark) #collection-form .form-input::placeholder,\n html:not(.dark) #collection-form .form-textarea::placeholder {\n color: #71717a; /* zinc-500 */\n }\n\n .dark #collection-form .form-input::placeholder,\n .dark #collection-form .form-textarea::placeholder {\n color: #71717a; /* zinc-500 */\n }\n\n #collection-form .btn {\n padding: 0.625rem 1rem;\n font-weight: 600;\n font-size: 0.875rem;\n border-radius: 0.5rem;\n transition: all 0.15s;\n border: none;\n cursor: pointer;\n }\n\n html:not(.dark) #collection-form .btn-primary {\n background: #09090b; /* zinc-950 */\n color: white;\n }\n\n html:not(.dark) #collection-form .btn-primary:hover {\n background: #27272a; /* zinc-800 */\n }\n\n .dark #collection-form .btn-primary {\n background: white;\n color: #09090b; /* zinc-950 */\n }\n\n .dark #collection-form .btn-primary:hover {\n background: #f4f4f5; /* zinc-100 */\n }\n\n #collection-form .form-help-text {\n font-size: 0.75rem;\n margin-top: 0.25rem;\n }\n\n html:not(.dark) #collection-form .form-help-text {\n color: #71717a; /* zinc-500 */\n }\n\n .dark #collection-form .form-help-text {\n color: #a1a1aa; /* zinc-400 */\n }\n </style>\n \n ${renderForm(formData)}\n\n ${isEdit && data.managed ? `\n <!-- Read-Only Fields Display for Managed Collections -->\n <div class=\"mt-8 pt-8 border-t border-zinc-950/5 dark:border-white/10\">\n <div class=\"mb-6\">\n <h3 class=\"text-base/7 font-semibold text-zinc-950 dark:text-white\">Collection Fields</h3>\n <p class=\"text-sm/6 text-zinc-500 dark:text-zinc-400 mt-1\">Fields defined in the configuration file (read-only)</p>\n </div>\n\n <!-- Fields List (Read-Only) -->\n <div class=\"space-y-3\">\n ${fieldsWithData.map(field => `\n <div class=\"bg-zinc-50 dark:bg-zinc-800/50 rounded-lg border border-zinc-950/5 dark:border-white/10 p-4\">\n <div class=\"flex items-center justify-between\">\n <div class=\"flex items-center gap-x-4\">\n <div>\n <div class=\"flex items-center gap-x-2\">\n <span class=\"text-sm/6 font-medium text-zinc-950 dark:text-white\">${field.field_label}</span>\n ${getFieldTypeBadge(field.field_type)}\n ${field.is_required ? `\n <span class=\"inline-flex items-center rounded-md px-2 py-1 text-xs font-medium bg-rose-500/10 dark:bg-rose-400/10 text-rose-700 dark:text-rose-300 ring-1 ring-inset ring-rose-500/20 dark:ring-rose-400/20\">\n Required\n </span>\n ` : ''}\n ${field.is_searchable ? `\n <span class=\"inline-flex items-center rounded-md px-2 py-1 text-xs font-medium bg-emerald-500/10 dark:bg-emerald-400/10 text-emerald-700 dark:text-emerald-300 ring-1 ring-inset ring-emerald-500/20 dark:ring-emerald-400/20\">\n Searchable\n </span>\n ` : ''}\n </div>\n <div class=\"text-xs text-zinc-500 dark:text-zinc-400 mt-1\">\n <code class=\"px-1.5 py-0.5 rounded bg-zinc-100 dark:bg-zinc-800 font-mono\">${field.field_name}</code>\n </div>\n </div>\n </div>\n </div>\n </div>\n `).join('')}\n\n ${(data.fields || []).length === 0 ? `\n <div class=\"text-center py-12 text-zinc-500 dark:text-zinc-400\">\n <svg class=\"mx-auto h-12 w-12 text-zinc-400 dark:text-zinc-500\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\" stroke-width=\"1.5\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M19.5 14.25v-2.625a3.375 3.375 0 00-3.375-3.375h-1.5A1.125 1.125 0 0113.5 7.125v-1.5a3.375 3.375 0 00-3.375-3.375H8.25m0 12.75h7.5m-7.5 3H12M10.5 2.25H5.625c-.621 0-1.125.504-1.125 1.125v17.25c0 .621.504 1.125 1.125 1.125h12.75c.621 0 1.125-.504 1.125-1.125V11.25a9 9 0 00-9-9z\"/>\n </svg>\n <p class=\"mt-4 text-base/7 font-semibold text-zinc-950 dark:text-white\">No fields defined</p>\n <p class=\"mt-2 text-sm/6\">Add fields to your collection configuration file to see them here.</p>\n </div>\n ` : ''}\n </div>\n </div>\n ` : ''}\n\n ${isEdit && !data.managed ? `\n <!-- Fields Management Section -->\n <div class=\"mt-8 pt-8 border-t border-zinc-950/5 dark:border-white/10\">\n <div class=\"flex items-center justify-between mb-6\">\n <div>\n <h3 class=\"text-base/7 font-semibold text-zinc-950 dark:text-white\">Collection Fields</h3>\n <p class=\"text-sm/6 text-zinc-500 dark:text-zinc-400 mt-1\">Define the fields that content in this collection will have</p>\n </div>\n <button\n type=\"button\"\n onclick=\"showAddFieldModal()\"\n class=\"inline-flex items-center gap-x-1.5 px-3.5 py-2.5 bg-zinc-950 dark:bg-white text-white dark:text-zinc-950 font-semibold text-sm rounded-lg hover:bg-zinc-800 dark:hover:bg-zinc-100 transition-colors shadow-sm\"\n >\n <svg class=\"h-5 w-5\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\" stroke-width=\"2\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M12 4v16m8-8H4\"/>\n </svg>\n Add Field\n </button>\n </div>\n \n <!-- Fields List -->\n <div id=\"fields-list\" class=\"space-y-3\">\n ${fieldsWithData.map(field => `\n <div class=\"field-item bg-zinc-50 dark:bg-zinc-800/50 rounded-lg border border-zinc-950/5 dark:border-white/10 p-4\"\n data-field-id=\"${field.id}\"\n data-field-data=\"${field.dataFieldJSON}\">\n <div class=\"flex items-center justify-between\">\n <div class=\"flex items-center gap-x-4\">\n <div class=\"drag-handle cursor-move text-zinc-400 dark:text-zinc-500 hover:text-zinc-600 dark:hover:text-zinc-400\">\n <svg class=\"h-5 w-5\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\" stroke-width=\"2\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M4 8h16M4 16h16\"/>\n </svg>\n </div>\n <div>\n <div class=\"flex items-center gap-x-2\">\n <span class=\"text-sm/6 font-medium text-zinc-950 dark:text-white\">${field.field_label}</span>\n ${getFieldTypeBadge(field.field_type)}\n ${field.is_required ? `\n <span class=\"inline-flex items-center rounded-md px-2 py-1 text-xs font-medium bg-pink-500/10 dark:bg-pink-400/10 text-pink-700 dark:text-pink-300 ring-1 ring-inset ring-pink-500/20 dark:ring-pink-400/20\">\n Required\n </span>\n ` : ''}\n ${field.is_searchable ? `\n <span class=\"inline-flex items-center rounded-md px-2 py-1 text-xs font-medium bg-emerald-500/10 dark:bg-emerald-400/10 text-emerald-700 dark:text-emerald-300 ring-1 ring-inset ring-emerald-500/20 dark:ring-emerald-400/20\">\n Searchable\n </span>\n ` : ''}\n </div>\n <div class=\"text-sm/6 text-zinc-500 dark:text-zinc-400 mt-1\">\n Field name: <code class=\"text-zinc-950 dark:text-white font-mono text-xs\">${field.field_name}</code>\n </div>\n </div>\n </div>\n <div class=\"flex items-center gap-x-2\">\n <button\n type=\"button\"\n onclick=\"editField('${field.id}')\"\n class=\"inline-flex items-center gap-x-1 px-2.5 py-1.5 text-sm font-medium text-zinc-950 dark:text-white hover:bg-zinc-100 dark:hover:bg-zinc-700 rounded-lg transition-colors\"\n >\n <svg class=\"h-4 w-4\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\" stroke-width=\"1.5\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M16.862 4.487l1.687-1.688a1.875 1.875 0 112.652 2.652L10.582 16.07a4.5 4.5 0 01-1.897 1.13L6 18l.8-2.685a4.5 4.5 0 011.13-1.897l8.932-8.931zm0 0L19.5 7.125M18 14v4.75A2.25 2.25 0 0115.75 21H5.25A2.25 2.25 0 013 18.75V8.25A2.25 2.25 0 015.25 6H10\"/>\n </svg>\n Edit\n </button>\n <button\n type=\"button\"\n onclick=\"deleteField('${field.id}')\"\n class=\"inline-flex items-center gap-x-1 px-2.5 py-1.5 text-sm font-medium text-pink-700 dark:text-pink-300 hover:bg-pink-50 dark:hover:bg-pink-900/20 rounded-lg transition-colors\"\n >\n <svg class=\"h-4 w-4\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\" stroke-width=\"1.5\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M14.74 9l-.346 9m-4.788 0L9.26 9m9.968-3.21c.342.052.682.107 1.022.166m-1.022-.165L18.16 19.673a2.25 2.25 0 01-2.244 2.077H8.084a2.25 2.25 0 01-2.244-2.077L4.772 5.79m14.456 0a48.108 48.108 0 00-3.478-.397m-12 .562c.34-.059.68-.114 1.022-.165m0 0a48.11 48.11 0 013.478-.397m7.5 0v-.916c0-1.18-.91-2.164-2.09-2.201a51.964 51.964 0 00-3.32 0c-1.18.037-2.09 1.022-2.09 2.201v.916m7.5 0a48.667 48.667 0 00-7.5 0\"/>\n </svg>\n Delete\n </button>\n </div>\n </div>\n </div>\n `).join('')}\n\n ${(data.fields || []).length === 0 ? `\n <div class=\"text-center py-12 text-zinc-500 dark:text-zinc-400\">\n <svg class=\"mx-auto h-12 w-12 text-zinc-400 dark:text-zinc-500\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\" stroke-width=\"1.5\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M19.5 14.25v-2.625a3.375 3.375 0 00-3.375-3.375h-1.5A1.125 1.125 0 0113.5 7.125v-1.5a3.375 3.375 0 00-3.375-3.375H8.25m0 12.75h7.5m-7.5 3H12M10.5 2.25H5.625c-.621 0-1.125.504-1.125 1.125v17.25c0 .621.504 1.125 1.125 1.125h12.75c.621 0 1.125-.504 1.125-1.125V11.25a9 9 0 00-9-9z\"/>\n </svg>\n <p class=\"mt-4 text-base/7 font-semibold text-zinc-950 dark:text-white\">No fields defined</p>\n <p class=\"mt-2 text-sm/6\">Add your first field to get started</p>\n </div>\n ` : ''}\n </div>\n </div>\n ` : `\n <div class=\"mt-6 rounded-lg bg-cyan-50 dark:bg-cyan-900/20 border border-cyan-100 dark:border-cyan-900/30 p-4\">\n <div class=\"flex items-start gap-x-3\">\n <svg class=\"h-5 w-5 text-cyan-600 dark:text-cyan-400 mt-0.5\" fill=\"currentColor\" viewBox=\"0 0 20 20\">\n <path fill-rule=\"evenodd\" d=\"M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7-4a1 1 0 11-2 0 1 1 0 012 0zM9 9a1 1 0 000 2v3a1 1 0 001 1h1a1 1 0 100-2v-3a1 1 0 00-1-1H9z\" clip-rule=\"evenodd\"/>\n </svg>\n <div>\n <h3 class=\"text-sm/6 font-medium text-cyan-900 dark:text-cyan-300\">\n Create Collection First\n </h3>\n <p class=\"text-sm/6 text-cyan-800 dark:text-cyan-400 mt-1\">\n After creating the collection, you'll be able to add and configure custom fields.\n </p>\n </div>\n </div>\n </div>\n `}\n \n <!-- Action Buttons -->\n <div class=\"mt-6 pt-6 border-t border-zinc-950/5 dark:border-white/10 flex items-center justify-between\">\n <a href=\"/admin/collections\" class=\"inline-flex items-center justify-center gap-x-1.5 rounded-lg bg-white dark:bg-zinc-800 px-3.5 py-2.5 text-sm font-semibold text-zinc-950 dark:text-white ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 hover:bg-zinc-50 dark:hover:bg-zinc-700 transition-colors shadow-sm\">\n <svg class=\"h-5 w-5\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\" stroke-width=\"1.5\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M6 18L18 6M6 6l12 12\"/>\n </svg>\n ${data.managed ? 'Back to Collections' : 'Cancel'}\n </a>\n\n ${isEdit && !data.managed ? `\n <button\n type=\"button\"\n hx-delete=\"/admin/collections/${data.id}\"\n hx-confirm=\"Are you sure you want to delete this collection? This action cannot be undone.\"\n hx-target=\"body\"\n class=\"inline-flex items-center justify-center gap-x-1.5 rounded-lg bg-pink-600 dark:bg-pink-500 px-3.5 py-2.5 text-sm font-semibold text-white hover:bg-pink-700 dark:hover:bg-pink-600 transition-colors shadow-sm\"\n >\n <svg class=\"h-5 w-5\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\" stroke-width=\"1.5\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M14.74 9l-.346 9m-4.788 0L9.26 9m9.968-3.21c.342.052.682.107 1.022.166m-1.022-.165L18.16 19.673a2.25 2.25 0 01-2.244 2.077H8.084a2.25 2.25 0 01-2.244-2.077L4.772 5.79m14.456 0a48.108 48.108 0 00-3.478-.397m-12 .562c.34-.059.68-.114 1.022-.165m0 0a48.11 48.11 0 013.478-.397m7.5 0v-.916c0-1.18-.91-2.164-2.09-2.201a51.964 51.964 0 00-3.32 0c-1.18.037-2.09 1.022-2.09 2.201v.916m7.5 0a48.667 48.667 0 00-7.5 0\"/>\n </svg>\n Delete Collection\n </button>\n ` : ''}\n </div>\n </div>\n </div>\n </div>\n\n <!-- Add/Edit Field Modal -->\n <div id=\"field-modal\" class=\"fixed inset-0 bg-black/50 backdrop-blur-sm flex items-center justify-center z-50 hidden\">\n <div class=\"rounded-xl bg-white dark:bg-zinc-900 shadow-xl ring-1 ring-zinc-950/5 dark:ring-white/10 w-full max-w-lg mx-4\">\n <div class=\"px-6 py-4 border-b border-zinc-950/5 dark:border-white/10\">\n <div class=\"flex items-center justify-between\">\n <h3 id=\"modal-title\" class=\"text-lg font-semibold text-zinc-950 dark:text-white\">Add Field</h3>\n <button onclick=\"closeFieldModal()\" class=\"text-zinc-500 dark:text-zinc-400 hover:text-zinc-950 dark:hover:text-white transition-colors\">\n <svg class=\"w-6 h-6\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M6 18L18 6M6 6l12 12\"></path>\n </svg>\n </button>\n </div>\n </div>\n\n <form id=\"field-form\" class=\"p-6 space-y-4\">\n <input type=\"hidden\" id=\"field-id\" name=\"field_id\">\n\n <div>\n <label class=\"block text-sm font-medium text-zinc-950 dark:text-white mb-2\">Field Name</label>\n <input\n type=\"text\"\n id=\"modal-field-name\"\n name=\"field_name\"\n required\n pattern=\"[a-z0-9_]+\"\n class=\"w-full rounded-lg bg-white dark:bg-zinc-800 px-4 py-3 text-sm text-zinc-950 dark:text-white placeholder-zinc-500 dark:placeholder-zinc-400 ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 focus:ring-2 focus:ring-blue-600 dark:focus:ring-blue-500 focus:outline-none transition-colors\"\n placeholder=\"field_name\"\n >\n <p class=\"text-xs text-zinc-500 dark:text-zinc-400 mt-1\">Lowercase letters, numbers, and underscores only</p>\n </div>\n\n <div>\n <label for=\"field-type\" class=\"block text-sm/6 font-medium text-zinc-950 dark:text-white\">Field Type</label>\n <div class=\"mt-2 grid grid-cols-1\">\n <select\n id=\"field-type\"\n name=\"field_type\"\n required\n class=\"col-start-1 row-start-1 w-full appearance-none rounded-md bg-white/5 dark:bg-white/5 py-1.5 pl-3 pr-8 text-base text-zinc-950 dark:text-white outline outline-1 -outline-offset-1 outline-blue-500/30 dark:outline-blue-400/30 *:bg-white dark:*:bg-zinc-800 focus-visible:outline focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-blue-500 dark:focus-visible:outline-blue-400 sm:text-sm/6\"\n >\n <option value=\"\">Select field type...</option>\n <option value=\"text\">Text</option>\n ${data.editorPlugins?.tinymce ? '<option value=\"richtext\">Rich Text (TinyMCE)</option>' : ''}\n ${data.editorPlugins?.quill ? '<option value=\"quill\">Rich Text (Quill)</option>' : ''}\n ${data.editorPlugins?.easyMdx ? '<option value=\"mdxeditor\">EasyMDX</option>' : ''}\n <option value=\"number\">Number</option>\n <option value=\"boolean\">Boolean</option>\n <option value=\"date\">Date</option>\n <option value=\"select\">Select</option>\n <option value=\"media\">Media</option>\n </select>\n <svg viewBox=\"0 0 16 16\" fill=\"currentColor\" data-slot=\"icon\" aria-hidden=\"true\" class=\"pointer-events-none col-start-1 row-start-1 mr-2 size-5 self-center justify-self-end text-blue-600 dark:text-blue-400 sm:size-4\">\n <path d=\"M4.22 6.22a.75.75 0 0 1 1.06 0L8 8.94l2.72-2.72a.75.75 0 1 1 1.06 1.06l-3.25 3.25a.75.75 0 0 1-1.06 0L4.22 7.28a.75.75 0 0 1 0-1.06Z\" clip-rule=\"evenodd\" fill-rule=\"evenodd\" />\n </svg>\n </div>\n <p id=\"field-type-help\" class=\"text-xs text-zinc-500 dark:text-zinc-400 mt-1\"></p>\n </div>\n\n <div>\n <label class=\"block text-sm font-medium text-zinc-950 dark:text-white mb-2\">Field Label</label>\n <input\n type=\"text\"\n id=\"field-label\"\n name=\"field_label\"\n required\n class=\"w-full rounded-lg bg-white dark:bg-zinc-800 px-4 py-3 text-sm text-zinc-950 dark:text-white placeholder-zinc-500 dark:placeholder-zinc-400 ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 focus:ring-2 focus:ring-blue-600 dark:focus:ring-blue-500 focus:outline-none transition-colors\"\n placeholder=\"Field Label\"\n >\n </div>\n\n <div class=\"flex items-center space-x-6\">\n <div class=\"flex gap-3\">\n <div class=\"flex h-6 shrink-0 items-center\">\n <div class=\"group grid size-4 grid-cols-1\">\n <input type=\"hidden\" name=\"is_required\" value=\"0\">\n <input\n type=\"checkbox\"\n id=\"field-required\"\n name=\"is_required\"\n value=\"1\"\n class=\"col-start-1 row-start-1 appearance-none rounded border border-zinc-950/10 dark:border-white/10 bg-white dark:bg-white/5 checked:border-indigo-500 checked:bg-indigo-500 indeterminate:border-indigo-500 indeterminate:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-500 disabled:border-zinc-950/5 dark:disabled:border-white/5 disabled:bg-zinc-950/10 dark:disabled:bg-white/10 disabled:checked:bg-zinc-950/10 dark:disabled:checked:bg-white/10 forced-colors:appearance-auto\"\n />\n <svg viewBox=\"0 0 14 14\" fill=\"none\" class=\"pointer-events-none col-start-1 row-start-1 size-3.5 self-center justify-self-center stroke-white group-has-[:disabled]:stroke-zinc-950/25 dark:group-has-[:disabled]:stroke-white/25\">\n <path d=\"M3 8L6 11L11 3.5\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"opacity-0 group-has-[:checked]:opacity-100\" />\n <path d=\"M3 7H11\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"opacity-0 group-has-[:indeterminate]:opacity-100\" />\n </svg>\n </div>\n </div>\n <div class=\"text-sm/6\">\n <label for=\"field-required\" class=\"font-medium text-zinc-950 dark:text-white\">Required</label>\n </div>\n </div>\n\n <div class=\"flex gap-3\">\n <div class=\"flex h-6 shrink-0 items-center\">\n <div class=\"group grid size-4 grid-cols-1\">\n <input type=\"hidden\" name=\"is_searchable\" value=\"0\">\n <input\n type=\"checkbox\"\n id=\"field-searchable\"\n name=\"is_searchable\"\n value=\"1\"\n class=\"col-start-1 row-start-1 appearance-none rounded border border-zinc-950/10 dark:border-white/10 bg-white dark:bg-white/5 checked:border-indigo-500 checked:bg-indigo-500 indeterminate:border-indigo-500 indeterminate:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-500 disabled:border-zinc-950/5 dark:disabled:border-white/5 disabled:bg-zinc-950/10 dark:disabled:bg-white/10 disabled:checked:bg-zinc-950/10 dark:disabled:checked:bg-white/10 forced-colors:appearance-auto\"\n />\n <svg viewBox=\"0 0 14 14\" fill=\"none\" class=\"pointer-events-none col-start-1 row-start-1 size-3.5 self-center justify-self-center stroke-white group-has-[:disabled]:stroke-zinc-950/25 dark:group-has-[:disabled]:stroke-white/25\">\n <path d=\"M3 8L6 11L11 3.5\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"opacity-0 group-has-[:checked]:opacity-100\" />\n <path d=\"M3 7H11\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"opacity-0 group-has-[:indeterminate]:opacity-100\" />\n </svg>\n </div>\n </div>\n <div class=\"text-sm/6\">\n <label for=\"field-searchable\" class=\"font-medium text-zinc-950 dark:text-white\">Searchable</label>\n </div>\n </div>\n </div>\n\n <div id=\"field-options-container\" class=\"hidden\">\n <label class=\"block text-sm font-medium text-zinc-950 dark:text-white mb-2\">Field Options (JSON)</label>\n <textarea\n id=\"field-options\"\n name=\"field_options\"\n rows=\"3\"\n class=\"w-full rounded-lg bg-white dark:bg-zinc-800 px-4 py-3 text-sm text-zinc-950 dark:text-white placeholder-zinc-500 dark:placeholder-zinc-400 ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 focus:ring-2 focus:ring-blue-600 dark:focus:ring-blue-500 focus:outline-none transition-colors font-mono\"\n placeholder='{\"maxLength\": 200, \"placeholder\": \"Enter text...\"}'\n ></textarea>\n <p class=\"text-xs text-zinc-500 dark:text-zinc-400 mt-1\">JSON configuration for field-specific options</p>\n </div>\n\n <div class=\"flex justify-end space-x-3 pt-4 border-t border-zinc-950/5 dark:border-white/10\">\n <button\n type=\"button\"\n onclick=\"closeFieldModal()\"\n class=\"rounded-lg bg-white dark:bg-zinc-800 px-4 py-2 text-sm font-semibold text-zinc-950 dark:text-white ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 hover:bg-zinc-50 dark:hover:bg-zinc-700 transition-colors\"\n >\n Cancel\n </button>\n <button\n type=\"submit\"\n class=\"rounded-lg bg-blue-600 px-4 py-2 text-sm font-semibold text-white hover:bg-blue-700 transition-colors\"\n >\n <span id=\"submit-text\">Add Field</span>\n </button>\n </div>\n </form>\n </div>\n </div>\n\n <script>\n const collectionId = '${data.id || ''}';\n \n \n let currentEditingField = null;\n\n // Field modal functions\n function showAddFieldModal() {\n document.getElementById('modal-title').textContent = 'Add Field';\n document.getElementById('submit-text').textContent = 'Add Field';\n document.getElementById('field-form').reset();\n document.getElementById('field-id').value = '';\n document.getElementById('modal-field-name').disabled = false;\n currentEditingField = null;\n isEditingField = false; // Allow change handlers for add mode\n document.getElementById('field-modal').classList.remove('hidden');\n }\n\n function editField(fieldId) {\n const fieldItem = document.querySelector(\\`[data-field-id=\"\\${fieldId}\"]\\`);\n if (!fieldItem) {\n console.error('Field item not found:', fieldId);\n return;\n }\n\n // Get field data from data attribute (primary source) or embedded array (fallback)\n let field = null;\n\n // Try to get from data attribute first\n const fieldDataAttr = fieldItem.getAttribute('data-field-data');\n if (fieldDataAttr) {\n try {\n // Data is double-JSON encoded to properly escape all special characters\n field = JSON.parse(JSON.parse(fieldDataAttr));\n console.log('Loaded field data from data attribute:', field);\n } catch (e) {\n console.error('Error parsing field data from attribute:', e);\n // Try single parse as fallback for backwards compatibility\n try {\n field = JSON.parse(fieldDataAttr);\n console.log('Loaded field data from data attribute (single parse):', field);\n } catch (e2) {\n console.error('Error parsing field data (fallback):', e2);\n }\n }\n }\n\n // Fallback to embedded array\n if (!field) {\n const fields = ${JSON.stringify(data.fields || [])};\n field = fields.find(f => f.id === fieldId);\n console.log('Loaded field data from embedded array:', field);\n }\n\n if (!field) {\n console.error('Field data not found for id:', fieldId);\n return;\n }\n\n // Set up the modal for editing\n document.getElementById('modal-title').textContent = 'Edit Field';\n document.getElementById('submit-text').textContent = 'Update Field';\n document.getElementById('field-id').value = fieldId;\n currentEditingField = fieldId;\n\n // Show modal FIRST before populating fields\n document.getElementById('field-modal').classList.remove('hidden');\n\n // Set flag to prevent change event handlers from interfering\n isEditingField = true;\n\n // Use setTimeout to ensure modal is rendered before setting values\n setTimeout(() => {\n // Populate form with existing field data\n console.log('Field object for editing:', field);\n console.log('field.field_name:', field.field_name);\n console.log('field.field_type:', field.field_type);\n console.log('field.field_label:', field.field_label);\n\n const fieldNameInput = document.getElementById('modal-field-name');\n const fieldTypeSelect = document.getElementById('field-type');\n const fieldLabelInput = document.getElementById('field-label');\n\n console.log('Field name input element:', fieldNameInput);\n console.log('Field type select element:', fieldTypeSelect);\n console.log('Field label input element:', fieldLabelInput);\n\n if (fieldNameInput) {\n console.log('Before setting - field-name value:', fieldNameInput.value);\n console.log('Before setting - field-name disabled:', fieldNameInput.disabled);\n\n fieldNameInput.disabled = false; // Enable first to ensure value can be set\n fieldNameInput.value = field.field_name || '';\n fieldNameInput.disabled = true; // Then disable\n\n console.log('After setting - field-name value:', fieldNameInput.value);\n console.log('After setting - field-name disabled:', fieldNameInput.disabled);\n\n // Verify the value stuck\n setTimeout(() => {\n console.log('After 100ms - field-name value:', fieldNameInput.value);\n }, 100);\n } else {\n console.error('field-name input not found!');\n }\n\n if (fieldLabelInput) {\n fieldLabelInput.value = field.field_label || '';\n console.log('Set field-label to:', fieldLabelInput.value);\n } else {\n console.error('field-label input not found!');\n }\n\n if (fieldTypeSelect) {\n // Map schema types to UI field types\n let uiFieldType = field.field_type || '';\n\n // Check if it's a schema field with field_options that might indicate the actual type\n if (field.field_options && typeof field.field_options === 'object') {\n // Only convert to richtext if type is explicitly 'string' and format is richtext\n // Don't convert if it's already a specific editor type like 'mdxeditor', 'quill', etc.\n if (field.field_options.format === 'richtext' && uiFieldType === 'string') {\n uiFieldType = 'richtext';\n }\n // Check for other format indicators\n else if (field.field_options.type && !uiFieldType) {\n uiFieldType = field.field_options.type;\n }\n }\n\n // Map common schema types to UI types\n const typeMapping = {\n 'string': 'text',\n 'integer': 'number',\n 'bool': 'boolean'\n };\n\n if (typeMapping[uiFieldType]) {\n uiFieldType = typeMapping[uiFieldType];\n }\n\n // Log all available options\n const availableOptions = Array.from(fieldTypeSelect.options).map(opt => ({ value: opt.value, text: opt.text }));\n console.log('Available dropdown options:', availableOptions);\n console.log('Trying to set field-type to:', uiFieldType);\n\n // Clear any existing selections first\n Array.from(fieldTypeSelect.options).forEach(opt => opt.selected = false);\n\n // Try multiple approaches to set the value\n let selectionSucceeded = false;\n\n // Approach 1: Direct value assignment\n fieldTypeSelect.value = uiFieldType;\n if (fieldTypeSelect.value === uiFieldType) {\n selectionSucceeded = true;\n console.log('✓ Approach 1 (direct value) succeeded');\n }\n\n // Approach 2: Find and select the specific option\n if (!selectionSucceeded) {\n console.log('Approach 1 failed, trying approach 2 (direct option selection)');\n const optionToSelect = Array.from(fieldTypeSelect.options).find(opt => opt.value === uiFieldType);\n if (optionToSelect) {\n optionToSelect.selected = true;\n // Trigger change event\n fieldTypeSelect.dispatchEvent(new Event('change', { bubbles: true }));\n if (fieldTypeSelect.value === uiFieldType) {\n selectionSucceeded = true;\n console.log('✓ Approach 2 (option.selected) succeeded');\n }\n }\n }\n\n // Approach 3: Set selectedIndex\n if (!selectionSucceeded) {\n console.log('Approach 2 failed, trying approach 3 (selectedIndex)');\n const optionIndex = Array.from(fieldTypeSelect.options).findIndex(opt => opt.value === uiFieldType);\n if (optionIndex !== -1) {\n fieldTypeSelect.selectedIndex = optionIndex;\n if (fieldTypeSelect.value === uiFieldType) {\n selectionSucceeded = true;\n console.log('✓ Approach 3 (selectedIndex) succeeded');\n }\n }\n }\n\n console.log('Final field-type value:', fieldTypeSelect.value, '(wanted:', uiFieldType, ')');\n\n if (!selectionSucceeded) {\n console.error('❌ All approaches failed to set field-type!');\n console.error('Wanted:', uiFieldType);\n console.error('Got:', fieldTypeSelect.value);\n console.error('Available options:', availableOptions);\n }\n } else {\n console.error('field-type select not found!');\n }\n\n const requiredCheckbox = document.getElementById('field-required');\n const searchableCheckbox = document.getElementById('field-searchable');\n\n if (requiredCheckbox) {\n requiredCheckbox.checked = Boolean(field.is_required);\n }\n\n if (searchableCheckbox) {\n searchableCheckbox.checked = Boolean(field.is_searchable);\n }\n\n // Handle field options - serialize object back to JSON string\n if (field.field_options) {\n document.getElementById('field-options').value = typeof field.field_options === 'string'\n ? field.field_options\n : JSON.stringify(field.field_options, null, 2);\n } else {\n document.getElementById('field-options').value = '';\n }\n\n // Show/hide options container based on field type\n const fieldType = field.field_type;\n const optionsContainer = document.getElementById('field-options-container');\n const helpText = document.getElementById('field-type-help');\n\n if (['select', 'media', 'richtext'].includes(fieldType)) {\n optionsContainer.classList.remove('hidden');\n\n // Set help text based on type\n switch (fieldType) {\n case 'select':\n helpText.textContent = 'Create a dropdown select field with custom options';\n break;\n case 'media':\n helpText.textContent = 'Upload and manage media files (images, videos, documents)';\n break;\n case 'richtext':\n helpText.textContent = 'Full-featured WYSIWYG text editor with formatting options';\n break;\n }\n } else {\n optionsContainer.classList.add('hidden');\n\n // Set help text for other field types\n switch (fieldType) {\n case 'text':\n helpText.textContent = 'Single-line text input for short content';\n break;\n case 'number':\n helpText.textContent = 'Numeric input field for integers or decimals';\n break;\n case 'boolean':\n helpText.textContent = 'True/false checkbox field';\n break;\n case 'date':\n helpText.textContent = 'Date and time picker field';\n break;\n default:\n helpText.textContent = '';\n }\n }\n\n // Clear the flag after a short delay to allow all events to settle\n setTimeout(() => {\n isEditingField = false;\n console.log('Cleared isEditingField flag');\n\n // Double-check the field-type value after the flag is cleared\n const finalCheck = document.getElementById('field-type');\n if (finalCheck) {\n console.log('Post-flag-clear check - field-type value:', finalCheck.value);\n }\n }, 200); // Increased delay\n\n }, 50); // Increased delay to ensure modal is fully rendered\n }\n\n function closeFieldModal() {\n document.getElementById('field-modal').classList.add('hidden');\n currentEditingField = null;\n isEditingField = false; // Clear the flag when closing\n }\n\n let fieldToDelete = null;\n\n function deleteField(fieldId) {\n fieldToDelete = fieldId;\n showConfirmDialog('delete-field-confirm');\n }\n\n function performDeleteField() {\n if (!fieldToDelete) return;\n\n fetch(\\`/admin/collections/\\${collectionId}/fields/\\${fieldToDelete}\\`, {\n method: 'DELETE'\n })\n .then(response => response.json())\n .then(data => {\n if (data.success) {\n location.reload();\n } else {\n alert('Error deleting field: ' + data.error);\n }\n })\n .catch(error => {\n console.error('Error:', error);\n alert('Error deleting field');\n })\n .finally(() => {\n fieldToDelete = null;\n });\n }\n\n // Field form submission\n document.getElementById('field-form').addEventListener('submit', function(e) {\n e.preventDefault();\n \n if (!collectionId) {\n alert('Error: Collection ID is missing. Cannot save field.');\n return;\n }\n \n const formData = new FormData(this);\n const isEditing = currentEditingField !== null;\n \n const url = isEditing \n ? \\`/admin/collections/\\${collectionId}/fields/\\${currentEditingField}\\`\n : \\`/admin/collections/\\${collectionId}/fields\\`;\n \n const method = isEditing ? 'PUT' : 'POST';\n \n \n fetch(url, {\n method: method,\n body: formData\n })\n .then(response => {\n if (!response.ok) {\n throw new Error(\\`HTTP \\${response.status}: \\${response.statusText}\\`);\n }\n return response.json();\n })\n .then(data => {\n if (data.success) {\n location.reload();\n } else {\n alert('Error saving field: ' + (data.error || 'Unknown error'));\n }\n })\n .catch(error => {\n alert('Error saving field: ' + error.message);\n });\n });\n\n // Flag to prevent change handler during programmatic edits\n let isEditingField = false;\n\n // Field type change handler\n document.getElementById('field-type').addEventListener('change', function() {\n // Skip if we're programmatically setting values during edit\n if (isEditingField) {\n console.log('Skipping change handler - field is being edited');\n return;\n }\n\n const optionsContainer = document.getElementById('field-options-container');\n const fieldOptions = document.getElementById('field-options');\n const helpText = document.getElementById('field-type-help');\n const fieldNameInput = document.getElementById('modal-field-name');\n\n // Show/hide options based on field type\n if (['select', 'media', 'richtext', 'guid'].includes(this.value)) {\n optionsContainer.classList.remove('hidden');\n\n // Set default options and help text based on type\n switch (this.value) {\n case 'select':\n fieldOptions.value = '{\"options\": [\"Option 1\", \"Option 2\"], \"multiple\": false}';\n helpText.textContent = 'Create a dropdown select field with custom options';\n break;\n case 'media':\n fieldOptions.value = '{\"accept\": \"image/*\", \"maxSize\": \"10MB\"}';\n helpText.textContent = 'Upload and manage media files (images, videos, documents)';\n break;\n case 'richtext':\n fieldOptions.value = '{\"toolbar\": \"full\", \"height\": 400}';\n helpText.textContent = 'Full-featured WYSIWYG text editor with formatting options';\n break;\n }\n } else {\n optionsContainer.classList.add('hidden');\n fieldOptions.value = '{}';\n\n // Set help text for other field types\n switch (this.value) {\n case 'text':\n helpText.textContent = 'Single-line text input for short content';\n break;\n case 'number':\n helpText.textContent = 'Numeric input field for integers or decimals';\n break;\n case 'boolean':\n helpText.textContent = 'True/false checkbox field';\n break;\n case 'date':\n helpText.textContent = 'Date and time picker field';\n break;\n default:\n helpText.textContent = '';\n }\n }\n });\n\n // Close modal on escape key\n document.addEventListener('keydown', function(e) {\n if (e.key === 'Escape' && !document.getElementById('field-modal').classList.contains('hidden')) {\n closeFieldModal();\n }\n });\n\n // Close modal on backdrop click\n document.getElementById('field-modal').addEventListener('click', function(e) {\n if (e.target === this) {\n closeFieldModal();\n }\n });\n </script>\n\n <!-- Confirmation Dialogs -->\n ${renderConfirmationDialog({\n id: 'delete-field-confirm',\n title: 'Delete Field',\n message: 'Are you sure you want to delete this field? This action cannot be undone.',\n confirmText: 'Delete',\n cancelText: 'Cancel',\n iconColor: 'red',\n confirmClass: 'bg-red-500 hover:bg-red-400',\n onConfirm: 'performDeleteField()'\n })}\n\n ${getConfirmationDialogScript()}\n `\n\n const layoutData: AdminLayoutCatalystData = {\n title: title,\n pageTitle: 'Collections',\n currentPath: '/admin/collections',\n user: data.user,\n version: data.version,\n content: pageContent\n }\n\n return renderAdminLayoutCatalyst(layoutData)\n}","import { Hono } from 'hono'\nimport { html } from 'hono/html'\nimport { requireAuth } from '../middleware'\nimport { isPluginActive } from '../middleware/plugin-middleware'\nimport { renderCollectionsListPage } from '../templates/pages/admin-collections-list.template'\nimport { renderCollectionFormPage } from '../templates/pages/admin-collections-form.template'\n\n// Type definitions for collections\ninterface Collection {\n id: string\n name: string\n display_name: string\n description?: string\n created_at: number\n formattedDate: string\n field_count?: number\n managed?: boolean\n}\n\ninterface CollectionFormData {\n id?: string\n name?: string\n display_name?: string\n description?: string\n fields?: CollectionField[]\n managed?: boolean\n isEdit?: boolean\n error?: string\n success?: string\n user?: {\n name: string\n email: string\n role: string\n }\n version?: string\n editorPlugins?: {\n tinymce: boolean\n quill: boolean\n easyMdx: boolean\n }\n}\n\ninterface CollectionField {\n id: string\n field_name: string\n field_type: string\n field_label: string\n field_options: any\n field_order: number\n is_required: boolean\n is_searchable: boolean\n}\n\ninterface CollectionsListPageData {\n collections: Collection[]\n search?: string\n user?: {\n name: string\n email: string\n role: string\n }\n version?: string\n}\n\ntype Bindings = {\n DB: D1Database\n CACHE_KV: KVNamespace\n MEDIA_BUCKET: R2Bucket\n ASSETS: Fetcher\n EMAIL_QUEUE?: Queue\n SENDGRID_API_KEY?: string\n DEFAULT_FROM_EMAIL?: string\n IMAGES_ACCOUNT_ID?: string\n IMAGES_API_TOKEN?: string\n ENVIRONMENT?: string\n}\n\ntype Variables = {\n user?: {\n userId: string\n email: string\n role: string\n exp: number\n iat: number\n }\n requestId?: string\n startTime?: number\n appVersion?: string\n}\n\nexport const adminCollectionsRoutes = new Hono<{ Bindings: Bindings; Variables: Variables }>()\n\n// Apply authentication middleware\nadminCollectionsRoutes.use('*', requireAuth())\n\n// Collections management - List all collections\nadminCollectionsRoutes.get('/', async (c) => {\n try {\n const user = c.get('user')\n const db = c.env.DB\n const url = new URL(c.req.url)\n const search = url.searchParams.get('search') || ''\n\n // Build query based on search\n let stmt\n let results\n if (search) {\n stmt = db.prepare(`\n SELECT id, name, display_name, description, created_at, managed, schema\n FROM collections\n WHERE is_active = 1\n AND (name LIKE ? OR display_name LIKE ? OR description LIKE ?)\n ORDER BY created_at DESC\n `)\n const searchParam = `%${search}%`\n const queryResults = await stmt.bind(searchParam, searchParam, searchParam).all()\n results = queryResults.results\n } else {\n stmt = db.prepare('SELECT id, name, display_name, description, created_at, managed, schema FROM collections WHERE is_active = 1 ORDER BY created_at DESC')\n const queryResults = await stmt.all()\n results = queryResults.results\n }\n\n // Fetch field counts for all collections from content_fields table (legacy)\n const fieldCountStmt = db.prepare('SELECT collection_id, COUNT(*) as count FROM content_fields GROUP BY collection_id')\n const { results: fieldCountResults } = await fieldCountStmt.all()\n const fieldCounts = new Map((fieldCountResults || []).map((row: any) => [String(row.collection_id), Number(row.count)]))\n\n const collections: Collection[] = (results || [])\n .filter((row: any) => row && row.id)\n .map((row: any) => {\n // Calculate field count: use schema if available, otherwise use content_fields table\n let fieldCount = 0\n if (row.schema) {\n try {\n const schema = typeof row.schema === 'string' ? JSON.parse(row.schema) : row.schema\n if (schema && schema.properties) {\n fieldCount = Object.keys(schema.properties).length\n }\n } catch (e) {\n // If schema parsing fails, fall back to content_fields count\n fieldCount = fieldCounts.get(String(row.id)) || 0\n }\n } else {\n fieldCount = fieldCounts.get(String(row.id)) || 0\n }\n\n return {\n id: String(row.id || ''),\n name: String(row.name || ''),\n display_name: String(row.display_name || ''),\n description: row.description ? String(row.description) : undefined,\n created_at: Number(row.created_at || 0),\n formattedDate: row.created_at ? new Date(Number(row.created_at)).toLocaleDateString() : 'Unknown',\n field_count: fieldCount,\n managed: row.managed === 1\n }\n })\n\n const pageData: CollectionsListPageData = {\n collections,\n search,\n user: user ? {\n name: user.email,\n email: user.email,\n role: user.role\n } : undefined,\n version: c.get('appVersion')\n }\n\n return c.html(renderCollectionsListPage(pageData))\n } catch (error) {\n console.error('Error fetching collections:', error)\n const errorMessage = error instanceof Error ? error.message : String(error)\n return c.html(html`<p>Error loading collections: ${errorMessage}</p>`)\n }\n})\n\n// New collection form\nadminCollectionsRoutes.get('/new', async (c) => {\n const user = c.get('user')\n const db = c.env.DB\n\n // Check which editor plugins are active\n const [tinymceActive, quillActive, mdxeditorActive] = await Promise.all([\n isPluginActive(db, 'tinymce-plugin'),\n isPluginActive(db, 'quill-editor'),\n isPluginActive(db, 'easy-mdx')\n ])\n\n console.log('[Collections /new] Editor plugins status:', {\n tinymce: tinymceActive,\n quill: quillActive,\n easyMdx: mdxeditorActive\n })\n\n const formData: CollectionFormData = {\n isEdit: false,\n user: user ? {\n name: user.email,\n email: user.email,\n role: user.role\n } : undefined,\n version: c.get('appVersion'),\n editorPlugins: {\n tinymce: tinymceActive,\n quill: quillActive,\n easyMdx: mdxeditorActive\n }\n }\n\n return c.html(renderCollectionFormPage(formData))\n})\n\n// Create collection\nadminCollectionsRoutes.post('/', async (c) => {\n try {\n const formData = await c.req.formData()\n const name = formData.get('name') as string\n const displayName = formData.get('displayName') as string\n const description = formData.get('description') as string\n\n // Check if this is an HTMX request\n const isHtmx = c.req.header('HX-Request') === 'true'\n\n // Basic validation\n if (!name || !displayName) {\n const errorMsg = 'Name and display name are required.'\n if (isHtmx) {\n return c.html(html`\n <div class=\"bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded\">\n ${errorMsg}\n </div>\n `)\n } else {\n // For regular form submission, redirect back with error\n return c.redirect('/admin/collections/new')\n }\n }\n\n // Validate name format\n if (!/^[a-z0-9_]+$/.test(name)) {\n const errorMsg = 'Collection name must contain only lowercase letters, numbers, and underscores.'\n if (isHtmx) {\n return c.html(html`\n <div class=\"bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded\">\n ${errorMsg}\n </div>\n `)\n } else {\n return c.redirect('/admin/collections/new')\n }\n }\n\n const db = c.env.DB\n\n // Check if collection already exists\n const existingStmt = db.prepare('SELECT id FROM collections WHERE name = ?')\n const existing = await existingStmt.bind(name).first()\n\n if (existing) {\n const errorMsg = 'A collection with this name already exists.'\n if (isHtmx) {\n return c.html(html`\n <div class=\"bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded\">\n ${errorMsg}\n </div>\n `)\n } else {\n return c.redirect('/admin/collections/new')\n }\n }\n\n // Create basic schema for the collection\n const basicSchema = {\n type: \"object\",\n properties: {\n title: {\n type: \"string\",\n title: \"Title\",\n required: true\n },\n content: {\n type: \"string\",\n title: \"Content\",\n format: \"richtext\"\n },\n status: {\n type: \"string\",\n title: \"Status\",\n enum: [\"draft\", \"published\", \"archived\"],\n default: \"draft\"\n }\n },\n required: [\"title\"]\n }\n\n // Create collection\n const collectionId = crypto.randomUUID()\n const now = Date.now()\n\n const insertStmt = db.prepare(`\n INSERT INTO collections (id, name, display_name, description, schema, is_active, created_at, updated_at)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?)\n `)\n\n await insertStmt.bind(\n collectionId,\n name,\n displayName,\n description || null,\n JSON.stringify(basicSchema),\n 1, // is_active\n now,\n now\n ).run()\n\n // Clear cache (only if CACHE_KV is available)\n if (c.env.CACHE_KV) {\n try {\n await c.env.CACHE_KV.delete('cache:collections:all')\n await c.env.CACHE_KV.delete(`cache:collection:${name}`)\n } catch (e) {\n console.error('Error clearing cache:', e)\n }\n }\n\n if (isHtmx) {\n return c.html(html`\n <div class=\"bg-green-100 border border-green-400 text-green-700 px-4 py-3 rounded mb-4\">\n Collection created successfully! Redirecting to edit mode...\n <script>\n setTimeout(() => {\n window.location.href = '/admin/collections/${collectionId}';\n }, 1500);\n </script>\n </div>\n `)\n } else {\n // For regular form submission, redirect to edit page\n return c.redirect(`/admin/collections/${collectionId}`)\n }\n } catch (error) {\n console.error('Error creating collection:', error)\n const isHtmx = c.req.header('HX-Request') === 'true'\n\n if (isHtmx) {\n return c.html(html`\n <div class=\"bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded\">\n Failed to create collection. Please try again.\n </div>\n `)\n } else {\n return c.redirect('/admin/collections/new')\n }\n }\n})\n\n// Edit collection form\nadminCollectionsRoutes.get('/:id', async (c) => {\n const db = c.env.DB\n try {\n const id = c.req.param('id')\n const user = c.get('user')\n\n const stmt = db.prepare('SELECT * FROM collections WHERE id = ?')\n const collection = await stmt.bind(id).first() as any\n\n if (!collection) {\n // Check which editor plugins are active\n const [tinymceActive, quillActive, mdxeditorActive] = await Promise.all([\n isPluginActive(db, 'tinymce-plugin'),\n isPluginActive(db, 'quill-editor'),\n isPluginActive(db, 'easy-mdx')\n ])\n\n const formData: CollectionFormData = {\n isEdit: true,\n error: 'Collection not found.',\n user: user ? {\n name: user.email,\n email: user.email,\n role: user.role\n } : undefined,\n version: c.get('appVersion'),\n editorPlugins: {\n tinymce: tinymceActive,\n quill: quillActive,\n easyMdx: mdxeditorActive\n }\n }\n return c.html(renderCollectionFormPage(formData))\n }\n\n // Get collection fields - try schema first, then content_fields table\n let fields: CollectionField[] = []\n\n // If collection has a schema, parse it\n if (collection.schema) {\n try {\n const schema = typeof collection.schema === 'string' ? JSON.parse(collection.schema) : collection.schema\n if (schema && schema.properties) {\n // Convert schema properties to field format\n let fieldOrder = 0\n fields = Object.entries(schema.properties).map(([fieldName, fieldConfig]: [string, any]) => ({\n id: `schema-${fieldName}`,\n field_name: fieldName,\n field_type: fieldConfig.type || 'string',\n field_label: fieldConfig.title || fieldName,\n field_options: fieldConfig,\n field_order: fieldOrder++,\n is_required: fieldConfig.required === true || (schema.required && schema.required.includes(fieldName)),\n is_searchable: fieldConfig.searchable === true || false\n }))\n }\n } catch (e) {\n console.error('Error parsing collection schema:', e)\n }\n }\n\n // Fall back to content_fields table if no schema or parsing failed\n if (fields.length === 0) {\n const fieldsStmt = db.prepare(`\n SELECT * FROM content_fields\n WHERE collection_id = ?\n ORDER BY field_order ASC\n `)\n const { results: fieldsResults } = await fieldsStmt.bind(id).all()\n fields = (fieldsResults || []).map((row: any) => {\n let fieldOptions = {}\n if (row.field_options) {\n try {\n fieldOptions = typeof row.field_options === 'string' ? JSON.parse(row.field_options) : row.field_options\n } catch (e) {\n console.error('Error parsing field_options for field:', row.field_name, e)\n fieldOptions = {}\n }\n }\n return {\n id: row.id,\n field_name: row.field_name,\n field_type: row.field_type,\n field_label: row.field_label,\n field_options: fieldOptions,\n field_order: row.field_order,\n is_required: row.is_required === 1,\n is_searchable: row.is_searchable === 1\n }\n })\n }\n\n // Check which editor plugins are active\n const [tinymceActive, quillActive, mdxeditorActive] = await Promise.all([\n isPluginActive(db, 'tinymce-plugin'),\n isPluginActive(db, 'quill-editor'),\n isPluginActive(db, 'easy-mdx')\n ])\n\n console.log('[Collections /:id] Editor plugins status:', {\n tinymce: tinymceActive,\n quill: quillActive,\n easyMdx: mdxeditorActive\n })\n\n const formData: CollectionFormData = {\n id: collection.id,\n name: collection.name,\n display_name: collection.display_name,\n description: collection.description,\n fields: fields,\n managed: collection.managed === 1,\n isEdit: true,\n user: user ? {\n name: user.email,\n email: user.email,\n role: user.role\n } : undefined,\n version: c.get('appVersion'),\n editorPlugins: {\n tinymce: tinymceActive,\n quill: quillActive,\n easyMdx: mdxeditorActive\n }\n }\n\n return c.html(renderCollectionFormPage(formData))\n } catch (error) {\n console.error('Error fetching collection:', error)\n const user = c.get('user')\n\n // Check which editor plugins are active (even in error state)\n const [tinymceActive, quillActive, mdxeditorActive] = await Promise.all([\n isPluginActive(db, 'tinymce-plugin'),\n isPluginActive(db, 'quill-editor'),\n isPluginActive(db, 'easy-mdx')\n ])\n\n const formData: CollectionFormData = {\n isEdit: true,\n error: 'Failed to load collection.',\n user: user ? {\n name: user.email,\n email: user.email,\n role: user.role\n } : undefined,\n version: c.get('appVersion'),\n editorPlugins: {\n tinymce: tinymceActive,\n quill: quillActive,\n easyMdx: mdxeditorActive\n }\n }\n return c.html(renderCollectionFormPage(formData))\n }\n})\n\n// Update collection\nadminCollectionsRoutes.put('/:id', async (c) => {\n try {\n const id = c.req.param('id')\n const formData = await c.req.formData()\n const displayName = formData.get('displayName') as string\n const description = formData.get('description') as string\n\n if (!displayName) {\n return c.html(html`\n <div class=\"bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded\">\n Display name is required.\n </div>\n `)\n }\n\n const db = c.env.DB\n\n const updateStmt = db.prepare(`\n UPDATE collections\n SET display_name = ?, description = ?, updated_at = ?\n WHERE id = ?\n `)\n\n await updateStmt.bind(displayName, description || null, Date.now(), id).run()\n\n return c.html(html`\n <div class=\"bg-green-100 border border-green-400 text-green-700 px-4 py-3 rounded\">\n Collection updated successfully!\n </div>\n `)\n } catch (error) {\n console.error('Error updating collection:', error)\n return c.html(html`\n <div class=\"bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded\">\n Failed to update collection. Please try again.\n </div>\n `)\n }\n})\n\n// Delete collection\nadminCollectionsRoutes.delete('/:id', async (c) => {\n try {\n const id = c.req.param('id')\n const db = c.env.DB\n\n // Check if collection has content\n const contentStmt = db.prepare('SELECT COUNT(*) as count FROM content WHERE collection_id = ?')\n const contentResult = await contentStmt.bind(id).first() as any\n\n if (contentResult && contentResult.count > 0) {\n return c.html(html`\n <div class=\"bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded\">\n Cannot delete collection: it contains ${contentResult.count} content item(s). Delete all content first.\n </div>\n `)\n }\n\n // Delete collection fields first\n const deleteFieldsStmt = db.prepare('DELETE FROM content_fields WHERE collection_id = ?')\n await deleteFieldsStmt.bind(id).run()\n\n // Delete collection\n const deleteStmt = db.prepare('DELETE FROM collections WHERE id = ?')\n await deleteStmt.bind(id).run()\n\n return c.html(html`\n <script>\n window.location.href = '/admin/collections';\n </script>\n `)\n } catch (error) {\n console.error('Error deleting collection:', error)\n return c.html(html`\n <div class=\"bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded\">\n Failed to delete collection. Please try again.\n </div>\n `)\n }\n})\n\n// Add field to collection\nadminCollectionsRoutes.post('/:id/fields', async (c) => {\n try {\n const collectionId = c.req.param('id')\n const formData = await c.req.formData()\n const fieldName = formData.get('field_name') as string\n const fieldType = formData.get('field_type') as string\n const fieldLabel = formData.get('field_label') as string\n const isRequired = formData.get('is_required') === '1'\n const isSearchable = formData.get('is_searchable') === '1'\n const fieldOptions = formData.get('field_options') as string || '{}'\n\n if (!fieldName || !fieldType || !fieldLabel) {\n return c.json({ success: false, error: 'Field name, type, and label are required.' })\n }\n\n // Validate field name format\n if (!/^[a-z0-9_]+$/.test(fieldName)) {\n return c.json({ success: false, error: 'Field name must contain only lowercase letters, numbers, and underscores.' })\n }\n\n const db = c.env.DB\n\n // Check if field already exists\n const existingStmt = db.prepare('SELECT id FROM content_fields WHERE collection_id = ? AND field_name = ?')\n const existing = await existingStmt.bind(collectionId, fieldName).first()\n\n if (existing) {\n return c.json({ success: false, error: 'A field with this name already exists.' })\n }\n\n // Get next field order\n const orderStmt = db.prepare('SELECT MAX(field_order) as max_order FROM content_fields WHERE collection_id = ?')\n const orderResult = await orderStmt.bind(collectionId).first() as any\n const nextOrder = (orderResult?.max_order || 0) + 1\n\n // Create field\n const fieldId = crypto.randomUUID()\n const now = Date.now()\n\n const insertStmt = db.prepare(`\n INSERT INTO content_fields (\n id, collection_id, field_name, field_type, field_label,\n field_options, field_order, is_required, is_searchable,\n created_at, updated_at\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n `)\n\n await insertStmt.bind(\n fieldId,\n collectionId,\n fieldName,\n fieldType,\n fieldLabel,\n fieldOptions,\n nextOrder,\n isRequired ? 1 : 0,\n isSearchable ? 1 : 0,\n now,\n now\n ).run()\n\n return c.json({ success: true, fieldId })\n } catch (error) {\n console.error('Error adding field:', error)\n return c.json({ success: false, error: 'Failed to add field.' })\n }\n})\n\n// Update field\nadminCollectionsRoutes.put('/:collectionId/fields/:fieldId', async (c) => {\n try {\n const fieldId = c.req.param('fieldId')\n const collectionId = c.req.param('collectionId')\n const formData = await c.req.formData()\n const fieldLabel = formData.get('field_label') as string\n const fieldType = formData.get('field_type') as string\n // Use getAll() to handle hidden input + checkbox pattern (get last value)\n const isRequiredValues = formData.getAll('is_required')\n const isSearchableValues = formData.getAll('is_searchable')\n const isRequired = isRequiredValues[isRequiredValues.length - 1] === '1'\n const isSearchable = isSearchableValues[isSearchableValues.length - 1] === '1'\n const fieldOptions = formData.get('field_options') as string || '{}'\n\n // Log all form data for debugging\n console.log('[Field Update] Field ID:', fieldId)\n console.log('[Field Update] Form data received:', {\n field_label: fieldLabel,\n field_type: fieldType,\n is_required: formData.get('is_required'),\n is_searchable: formData.get('is_searchable'),\n field_options: fieldOptions\n })\n\n if (!fieldLabel) {\n return c.json({ success: false, error: 'Field label is required.' })\n }\n\n const db = c.env.DB\n\n // Check if this is a schema field (starts with \"schema-\")\n if (fieldId.startsWith('schema-')) {\n // Schema fields are part of the collection's JSON schema\n // We need to update the collection's schema in the database\n const fieldName = fieldId.replace('schema-', '')\n\n console.log('[Field Update] Updating schema field:', fieldName)\n\n // Get the current collection\n const getCollectionStmt = db.prepare('SELECT * FROM collections WHERE id = ?')\n const collection = await getCollectionStmt.bind(collectionId).first()\n\n if (!collection) {\n return c.json({ success: false, error: 'Collection not found.' })\n }\n\n // Parse the current schema\n let schema = typeof collection.schema === 'string' ? JSON.parse(collection.schema) : collection.schema\n if (!schema) {\n schema = { type: 'object', properties: {}, required: [] }\n }\n if (!schema.properties) {\n schema.properties = {}\n }\n if (!schema.required) {\n schema.required = []\n }\n\n // Update the field in the schema\n if (schema.properties[fieldName]) {\n // Build the updated field config\n const updatedFieldConfig: any = {\n ...schema.properties[fieldName],\n type: fieldType,\n title: fieldLabel,\n searchable: isSearchable\n }\n\n // Also set/remove the individual required property on the field\n // This ensures consistency regardless of which format is checked in GET\n if (isRequired) {\n updatedFieldConfig.required = true\n } else {\n delete updatedFieldConfig.required\n }\n\n schema.properties[fieldName] = updatedFieldConfig\n\n // Handle required field in the schema's required array (proper JSON Schema way)\n const requiredIndex = schema.required.indexOf(fieldName)\n console.log('[Field Update] Required field handling:', {\n fieldName,\n isRequired,\n currentRequiredArray: schema.required,\n requiredIndex\n })\n\n if (isRequired && requiredIndex === -1) {\n // Add to required array if checked and not already there\n schema.required.push(fieldName)\n console.log('[Field Update] Added field to required array')\n } else if (!isRequired && requiredIndex !== -1) {\n // Remove from required array if unchecked and currently there\n schema.required.splice(requiredIndex, 1)\n console.log('[Field Update] Removed field from required array')\n }\n\n console.log('[Field Update] Final required array:', schema.required)\n console.log('[Field Update] Final field config:', schema.properties[fieldName])\n }\n\n // Update the collection in the database\n const updateCollectionStmt = db.prepare(`\n UPDATE collections\n SET schema = ?, updated_at = ?\n WHERE id = ?\n `)\n\n const result = await updateCollectionStmt.bind(JSON.stringify(schema), Date.now(), collectionId).run()\n\n console.log('[Field Update] Schema update result:', {\n success: result.success,\n changes: result.meta?.changes\n })\n\n return c.json({ success: true })\n }\n\n // For regular database fields\n const updateStmt = db.prepare(`\n UPDATE content_fields\n SET field_label = ?, field_type = ?, field_options = ?, is_required = ?, is_searchable = ?, updated_at = ?\n WHERE id = ?\n `)\n\n const result = await updateStmt.bind(fieldLabel, fieldType, fieldOptions, isRequired ? 1 : 0, isSearchable ? 1 : 0, Date.now(), fieldId).run()\n\n console.log('[Field Update] Update result:', {\n success: result.success,\n meta: result.meta,\n changes: result.meta?.changes,\n last_row_id: result.meta?.last_row_id\n })\n\n // Verify the update by reading back the field\n const verifyStmt = db.prepare('SELECT * FROM content_fields WHERE id = ?')\n const verifyResult = await verifyStmt.bind(fieldId).first()\n console.log('[Field Update] Verification - field after update:', verifyResult)\n\n console.log('[Field Update] Successfully updated field with type:', fieldType)\n\n return c.json({ success: true })\n } catch (error) {\n console.error('Error updating field:', error)\n return c.json({ success: false, error: 'Failed to update field.' })\n }\n})\n\n// Delete field\nadminCollectionsRoutes.delete('/:collectionId/fields/:fieldId', async (c) => {\n try {\n const fieldId = c.req.param('fieldId')\n const db = c.env.DB\n\n const deleteStmt = db.prepare('DELETE FROM content_fields WHERE id = ?')\n await deleteStmt.bind(fieldId).run()\n\n return c.json({ success: true })\n } catch (error) {\n console.error('Error deleting field:', error)\n return c.json({ success: false, error: 'Failed to delete field.' })\n }\n})\n\n// Update field order\nadminCollectionsRoutes.post('/:collectionId/fields/reorder', async (c) => {\n try {\n const body = await c.req.json()\n const fieldIds = body.fieldIds as string[]\n\n if (!Array.isArray(fieldIds)) {\n return c.json({ success: false, error: 'Invalid field order data.' })\n }\n\n const db = c.env.DB\n\n // Update field order\n for (let i = 0; i < fieldIds.length; i++) {\n const updateStmt = db.prepare('UPDATE content_fields SET field_order = ?, updated_at = ? WHERE id = ?')\n await updateStmt.bind(i + 1, Date.now(), fieldIds[i]).run()\n }\n\n return c.json({ success: true })\n } catch (error) {\n console.error('Error reordering fields:', error)\n return c.json({ success: false, error: 'Failed to reorder fields.' })\n }\n})\n","import { renderAdminLayoutCatalyst, AdminLayoutCatalystData } from '../layouts/admin-layout-catalyst.template'\nimport { renderConfirmationDialog, getConfirmationDialogScript } from '../components/confirmation-dialog.template'\n\nexport interface SettingsPageData {\n user?: {\n name: string\n email: string\n role: string\n }\n settings?: {\n general?: GeneralSettings\n appearance?: AppearanceSettings\n security?: SecuritySettings\n notifications?: NotificationSettings\n storage?: StorageSettings\n migrations?: MigrationSettings\n databaseTools?: DatabaseToolsSettings\n }\n activeTab?: string\n version?: string\n}\n\nexport interface GeneralSettings {\n siteName: string\n siteDescription: string\n adminEmail: string\n timezone: string\n language: string\n maintenanceMode: boolean\n}\n\nexport interface AppearanceSettings {\n theme: 'light' | 'dark' | 'auto'\n primaryColor: string\n logoUrl: string\n favicon: string\n customCSS: string\n}\n\nexport interface SecuritySettings {\n twoFactorEnabled: boolean\n sessionTimeout: number\n passwordRequirements: {\n minLength: number\n requireUppercase: boolean\n requireNumbers: boolean\n requireSymbols: boolean\n }\n ipWhitelist: string[]\n}\n\nexport interface NotificationSettings {\n emailNotifications: boolean\n contentUpdates: boolean\n systemAlerts: boolean\n userRegistrations: boolean\n emailFrequency: 'immediate' | 'daily' | 'weekly'\n}\n\nexport interface StorageSettings {\n maxFileSize: number\n allowedFileTypes: string[]\n storageProvider: 'local' | 'cloudflare' | 's3'\n backupFrequency: 'daily' | 'weekly' | 'monthly'\n retentionPeriod: number\n}\n\nexport interface MigrationSettings {\n totalMigrations: number\n appliedMigrations: number\n pendingMigrations: number\n lastApplied?: string\n migrations: Array<{\n id: string\n name: string\n filename: string\n description?: string\n applied: boolean\n appliedAt?: string\n size?: number\n }>\n}\n\nexport interface DatabaseToolsSettings {\n totalTables: number\n totalRows: number\n lastBackup?: string\n databaseSize?: string\n tables: Array<{\n name: string\n rowCount: number\n }>\n}\n\nexport function renderSettingsPage(data: SettingsPageData): string {\n const activeTab = data.activeTab || 'general'\n \n const pageContent = `\n <div>\n <!-- Header -->\n <div class=\"flex flex-col sm:flex-row sm:items-center sm:justify-between mb-6\">\n <div>\n <h1 class=\"text-2xl/8 font-semibold text-zinc-950 dark:text-white sm:text-xl/8\">Settings</h1>\n <p class=\"mt-2 text-sm/6 text-zinc-500 dark:text-zinc-400\">Manage your application settings and preferences</p>\n </div>\n </div>\n\n <!-- Settings Navigation Tabs -->\n <div class=\"rounded-xl bg-white dark:bg-zinc-900 shadow-sm ring-1 ring-zinc-950/5 dark:ring-white/10 mb-6 overflow-hidden\">\n <div class=\"border-b border-zinc-950/5 dark:border-white/10\">\n <nav class=\"flex overflow-x-auto\" role=\"tablist\">\n ${renderTabButton('general', 'General', 'M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z M15 12a3 3 0 11-6 0 3 3 0 016 0z', activeTab)}\n ${renderTabButton('appearance', 'Appearance', 'M7 21a4 4 0 01-4-4V5a2 2 0 012-2h4a2 2 0 012 2v12a4 4 0 01-4 4zM21 5a2 2 0 00-2-2h-4a2 2 0 00-2 2v12a4 4 0 004 4h4a2 2 0 002-2V5z', activeTab)}\n ${renderTabButton('security', 'Security', 'M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z', activeTab)}\n ${renderTabButton('notifications', 'Notifications', 'M15 17h5l-1.405-1.405A2.032 2.032 0 0118 14.158V11a6.002 6.002 0 00-4-5.659V5a2 2 0 10-4 0v.341C7.67 6.165 6 8.388 6 11v3.159c0 .538-.214 1.055-.595 1.436L4 17h5m6 0v1a3 3 0 11-6 0v-1m6 0H9', activeTab)}\n ${renderTabButton('storage', 'Storage', 'M7 16a4 4 0 01-.88-7.903A5 5 0 1115.9 6L16 6a5 5 0 011 9.9M15 13l-3-3m0 0l-3 3m3-3v12', activeTab)}\n ${renderTabButton('migrations', 'Migrations', 'M4 7v10c0 2.21 3.582 4 8 4s8-1.79 8-4V7M4 7c0 2.21 3.582 4 8 4s8-1.79 8-4M4 7c0-2.21 3.582-4 8-4s8 1.79 8 4m0 5c0 2.21-3.582 4-8 4s-8-1.79-8-4', activeTab)}\n ${renderTabButton('database-tools', 'Database Tools', 'M5 12h14M5 12a2 2 0 01-2-2V6a2 2 0 012-2h14a2 2 0 012 2v4a2 2 0 01-2 2M5 12a2 2 0 00-2 2v4a2 2 0 002 2h14a2 2 0 002-2v-4a2 2 0 00-2-2m-2-4h.01M17 16h.01', activeTab)}\n </nav>\n </div>\n </div>\n\n <!-- Settings Content -->\n <div class=\"rounded-xl bg-white dark:bg-zinc-900 shadow-sm ring-1 ring-zinc-950/5 dark:ring-white/10\">\n <div id=\"settings-content\" class=\"p-8\">\n ${renderTabContent(activeTab, data.settings)}\n </div>\n </div>\n </div>\n\n <script>\n // Initialize tab-specific features on page load\n const currentTab = '${activeTab}';\n\n async function saveGeneralSettings() {\n // Collect all form data from general settings\n const formData = new FormData();\n\n // Get all form inputs in the settings content area\n document.querySelectorAll('#settings-content input, #settings-content select, #settings-content textarea').forEach(input => {\n if (input.type === 'checkbox') {\n formData.append(input.name, input.checked ? 'true' : 'false');\n } else if (input.name) {\n formData.append(input.name, input.value);\n }\n });\n\n // Show loading state\n const saveBtn = document.querySelector('button[onclick=\"saveGeneralSettings()\"]');\n const originalText = saveBtn.innerHTML;\n saveBtn.innerHTML = '<svg class=\"animate-spin -ml-0.5 mr-1.5 h-5 w-5 inline\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\"><circle class=\"opacity-25\" cx=\"12\" cy=\"12\" r=\"10\" stroke=\"currentColor\" stroke-width=\"4\"></circle><path class=\"opacity-75\" fill=\"currentColor\" d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z\"></path></svg>Saving...';\n saveBtn.disabled = true;\n\n try {\n const response = await fetch('/admin/settings/general', {\n method: 'POST',\n body: formData\n });\n\n const result = await response.json();\n\n if (result.success) {\n showNotification(result.message || 'Settings saved successfully!', 'success');\n } else {\n showNotification(result.error || 'Failed to save settings', 'error');\n }\n } catch (error) {\n console.error('Error saving settings:', error);\n showNotification('Failed to save settings. Please try again.', 'error');\n } finally {\n saveBtn.innerHTML = originalText;\n saveBtn.disabled = false;\n }\n }\n\n // Migration functions\n window.refreshMigrationStatus = async function() {\n try {\n const response = await fetch('/admin/settings/api/migrations/status');\n const result = await response.json();\n \n if (result.success) {\n updateMigrationUI(result.data);\n } else {\n console.error('Failed to refresh migration status');\n }\n } catch (error) {\n console.error('Error loading migration status:', error);\n }\n };\n\n window.runPendingMigrations = async function() {\n const btn = document.getElementById('run-migrations-btn');\n if (!btn || btn.disabled) return;\n\n showConfirmDialog('run-migrations-confirm');\n };\n\n window.performRunMigrations = async function() {\n const btn = document.getElementById('run-migrations-btn');\n if (!btn) return;\n\n btn.disabled = true;\n btn.innerHTML = 'Running...';\n\n try {\n const response = await fetch('/admin/settings/api/migrations/run', {\n method: 'POST'\n });\n const result = await response.json();\n\n if (result.success) {\n alert(result.message);\n setTimeout(() => window.refreshMigrationStatus(), 1000);\n } else {\n alert(result.error || 'Failed to run migrations');\n }\n } catch (error) {\n alert('Error running migrations');\n } finally {\n btn.disabled = false;\n btn.innerHTML = 'Run Pending';\n }\n };\n\n window.validateSchema = async function() {\n try {\n const response = await fetch('/admin/settings/api/migrations/validate');\n const result = await response.json();\n \n if (result.success) {\n if (result.data.valid) {\n alert('Database schema is valid');\n } else {\n alert(\\`Schema validation failed: \\${result.data.issues.join(', ')}\\`);\n }\n } else {\n alert('Failed to validate schema');\n }\n } catch (error) {\n alert('Error validating schema');\n }\n };\n\n window.updateMigrationUI = function(data) {\n const totalEl = document.getElementById('total-migrations');\n const appliedEl = document.getElementById('applied-migrations');\n const pendingEl = document.getElementById('pending-migrations');\n \n if (totalEl) totalEl.textContent = data.totalMigrations;\n if (appliedEl) appliedEl.textContent = data.appliedMigrations;\n if (pendingEl) pendingEl.textContent = data.pendingMigrations;\n \n const runBtn = document.getElementById('run-migrations-btn');\n if (runBtn) {\n runBtn.disabled = data.pendingMigrations === 0;\n }\n \n // Update migrations list\n const listContainer = document.getElementById('migrations-list');\n if (listContainer && data.migrations && data.migrations.length > 0) {\n listContainer.innerHTML = data.migrations.map(migration => \\`\n <div class=\"px-6 py-4 flex items-center justify-between\">\n <div class=\"flex-1\">\n <div class=\"flex items-center space-x-3\">\n <div class=\"flex-shrink-0\">\n \\${migration.applied \n ? '<svg class=\"w-5 h-5 text-green-400\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\"><path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z\"/></svg>'\n : '<svg class=\"w-5 h-5 text-orange-400\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\"><path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z\"/></svg>'\n }\n </div>\n <div>\n <h5 class=\"text-white font-medium\">\\${migration.name}</h5>\n <p class=\"text-sm text-gray-300\">\\${migration.filename}</p>\n \\${migration.description ? \\`<p class=\"text-xs text-gray-400 mt-1\">\\${migration.description}</p>\\` : ''}\n </div>\n </div>\n </div>\n \n <div class=\"flex items-center space-x-4 text-sm\">\n \\${migration.size ? \\`<span class=\"text-gray-400\">\\${(migration.size / 1024).toFixed(1)} KB</span>\\` : ''}\n <span class=\"px-2 py-1 rounded-full text-xs font-medium \\${\n migration.applied \n ? 'bg-green-100 text-green-800' \n : 'bg-orange-100 text-orange-800'\n }\">\n \\${migration.applied ? 'Applied' : 'Pending'}\n </span>\n \\${migration.appliedAt ? \\`<span class=\"text-gray-400\">\\${new Date(migration.appliedAt).toLocaleDateString()}</span>\\` : ''}\n </div>\n </div>\n \\`).join('');\n }\n };\n \n // Auto-load migrations when switching to that tab\n function initializeMigrations() {\n if (currentTab === 'migrations') {\n setTimeout(window.refreshMigrationStatus, 500);\n }\n }\n \n // Database Tools functions\n window.refreshDatabaseStats = async function() {\n try {\n const response = await fetch('/admin/settings/api/database-tools/stats');\n const result = await response.json();\n \n if (result.success) {\n updateDatabaseToolsUI(result.data);\n } else {\n console.error('Failed to refresh database stats');\n }\n } catch (error) {\n console.error('Error loading database stats:', error);\n }\n };\n\n window.createDatabaseBackup = async function() {\n const btn = document.getElementById('create-backup-btn');\n if (!btn) return;\n \n btn.disabled = true;\n btn.innerHTML = 'Creating Backup...';\n \n try {\n const response = await fetch('/admin/settings/api/database-tools/backup', {\n method: 'POST'\n });\n const result = await response.json();\n \n if (result.success) {\n alert(result.message);\n setTimeout(() => window.refreshDatabaseStats(), 1000);\n } else {\n alert(result.error || 'Failed to create backup');\n }\n } catch (error) {\n alert('Error creating backup');\n } finally {\n btn.disabled = false;\n btn.innerHTML = 'Create Backup';\n }\n };\n\n window.truncateDatabase = async function() {\n // Show dangerous operation warning\n const confirmText = prompt(\n 'WARNING: This will delete ALL data except your admin account!\\\\n\\\\n' +\n 'This action CANNOT be undone!\\\\n\\\\n' +\n 'Type \"TRUNCATE ALL DATA\" to confirm:'\n );\n \n if (confirmText !== 'TRUNCATE ALL DATA') {\n alert('Operation cancelled. Confirmation text did not match.');\n return;\n }\n \n const btn = document.getElementById('truncate-db-btn');\n if (!btn) return;\n \n btn.disabled = true;\n btn.innerHTML = 'Truncating...';\n \n try {\n const response = await fetch('/admin/settings/api/database-tools/truncate', {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json'\n },\n body: JSON.stringify({\n confirmText: confirmText\n })\n });\n const result = await response.json();\n \n if (result.success) {\n alert(result.message + '\\\\n\\\\nTables cleared: ' + result.data.tablesCleared.join(', '));\n setTimeout(() => {\n window.refreshDatabaseStats();\n // Optionally reload page to refresh all data\n window.location.reload();\n }, 2000);\n } else {\n alert(result.error || 'Failed to truncate database');\n }\n } catch (error) {\n alert('Error truncating database');\n } finally {\n btn.disabled = false;\n btn.innerHTML = 'Truncate All Data';\n }\n };\n\n window.validateDatabase = async function() {\n try {\n const response = await fetch('/admin/settings/api/database-tools/validate');\n const result = await response.json();\n \n if (result.success) {\n if (result.data.valid) {\n alert('Database validation passed. No issues found.');\n } else {\n alert('Database validation failed:\\\\n\\\\n' + result.data.issues.join('\\\\n'));\n }\n } else {\n alert('Failed to validate database');\n }\n } catch (error) {\n alert('Error validating database');\n }\n };\n\n window.updateDatabaseToolsUI = function(data) {\n const totalTablesEl = document.getElementById('total-tables');\n const totalRowsEl = document.getElementById('total-rows');\n const tablesListEl = document.getElementById('tables-list');\n\n if (totalTablesEl) totalTablesEl.textContent = data.tables.length;\n if (totalRowsEl) totalRowsEl.textContent = data.totalRows.toLocaleString();\n\n if (tablesListEl && data.tables && data.tables.length > 0) {\n tablesListEl.innerHTML = data.tables.map(table => \\`\n <a\n href=\"/admin/database-tools/tables/\\${table.name}\"\n class=\"flex items-center justify-between py-3 px-4 rounded-lg bg-white dark:bg-white/5 hover:bg-zinc-50 dark:hover:bg-white/10 cursor-pointer transition-colors ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 no-underline\"\n >\n <div class=\"flex items-center space-x-3\">\n <svg class=\"w-5 h-5 text-zinc-500 dark:text-zinc-400\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M3 10h18M3 14h18m-9-4v8m-7 0h14a2 2 0 002-2V8a2 2 0 00-2-2H5a2 2 0 00-2 2v8a2 2 0 002 2z\"/>\n </svg>\n <span class=\"text-zinc-950 dark:text-white font-medium\">\\${table.name}</span>\n </div>\n <div class=\"flex items-center space-x-3\">\n <span class=\"text-zinc-500 dark:text-zinc-400 text-sm\">\\${table.rowCount.toLocaleString()} rows</span>\n <svg class=\"w-4 h-4 text-zinc-400\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M9 5l7 7-7 7\"/>\n </svg>\n </div>\n </a>\n \\`).join('');\n }\n };\n\n // Auto-load tab-specific data after all functions are defined\n if (currentTab === 'migrations') {\n setTimeout(window.refreshMigrationStatus, 500);\n }\n\n if (currentTab === 'database-tools') {\n setTimeout(window.refreshDatabaseStats, 500);\n }\n </script>\n\n <!-- Confirmation Dialogs -->\n ${renderConfirmationDialog({\n id: 'run-migrations-confirm',\n title: 'Run Migrations',\n message: 'Are you sure you want to run pending migrations? This action cannot be undone.',\n confirmText: 'Run Migrations',\n cancelText: 'Cancel',\n iconColor: 'blue',\n confirmClass: 'bg-blue-500 hover:bg-blue-400',\n onConfirm: 'performRunMigrations()'\n })}\n\n ${getConfirmationDialogScript()}\n `\n\n const layoutData: AdminLayoutCatalystData = {\n title: 'Settings',\n pageTitle: 'Settings',\n currentPath: '/admin/settings',\n user: data.user,\n version: data.version,\n content: pageContent\n }\n\n return renderAdminLayoutCatalyst(layoutData)\n}\n\nfunction renderTabButton(tabId: string, label: string, iconPath: string, activeTab: string): string {\n const isActive = activeTab === tabId\n const baseClasses = 'flex items-center space-x-2 px-4 py-3 text-sm font-medium transition-colors border-b-2 whitespace-nowrap no-underline'\n const activeClasses = isActive\n ? 'border-zinc-950 dark:border-white text-zinc-950 dark:text-white'\n : 'border-transparent text-zinc-500 dark:text-zinc-400 hover:text-zinc-700 dark:hover:text-zinc-300 hover:border-zinc-300 dark:hover:border-zinc-700'\n\n return `\n <a\n href=\"/admin/settings/${tabId}\"\n data-tab=\"${tabId}\"\n class=\"${baseClasses} ${activeClasses}\"\n >\n <svg class=\"w-4 h-4\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"${iconPath}\"/>\n </svg>\n <span>${label}</span>\n </a>\n `\n}\n\nfunction renderTabContent(activeTab: string, settings?: SettingsPageData['settings']): string {\n switch (activeTab) {\n case 'general':\n return renderGeneralSettings(settings?.general)\n case 'appearance':\n return renderAppearanceSettings(settings?.appearance)\n case 'security':\n return renderSecuritySettings(settings?.security)\n case 'notifications':\n return renderNotificationSettings(settings?.notifications)\n case 'storage':\n return renderStorageSettings(settings?.storage)\n case 'migrations':\n return renderMigrationSettings(settings?.migrations)\n case 'database-tools':\n return renderDatabaseToolsSettings(settings?.databaseTools)\n default:\n return renderGeneralSettings(settings?.general)\n }\n}\n\nfunction renderGeneralSettings(settings?: GeneralSettings): string {\n return `\n <div class=\"space-y-6\">\n <div>\n <h3 class=\"text-lg/7 font-semibold text-zinc-950 dark:text-white\">General Settings</h3>\n <p class=\"mt-1 text-sm/6 text-zinc-500 dark:text-zinc-400\">Configure basic application settings and preferences.</p>\n </div>\n \n <div class=\"grid grid-cols-1 md:grid-cols-2 gap-6\">\n <div class=\"space-y-4\">\n <div>\n <label class=\"block text-sm/6 font-medium text-zinc-950 dark:text-white mb-2\">Site Name</label>\n <input\n type=\"text\"\n name=\"siteName\"\n value=\"${settings?.siteName || 'SonicJS AI'}\"\n class=\"w-full rounded-lg bg-white dark:bg-white/5 px-3 py-2 text-sm/6 text-zinc-950 dark:text-white ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 placeholder:text-zinc-500 dark:placeholder:text-zinc-400 focus:ring-2 focus:ring-inset focus:ring-indigo-500 dark:focus:ring-indigo-400\"\n placeholder=\"Enter site name\"\n />\n </div>\n\n <div>\n <label class=\"block text-sm/6 font-medium text-zinc-950 dark:text-white mb-2\">Admin Email</label>\n <input\n type=\"email\"\n name=\"adminEmail\"\n value=\"${settings?.adminEmail || 'admin@example.com'}\"\n class=\"w-full rounded-lg bg-white dark:bg-white/5 px-3 py-2 text-sm/6 text-zinc-950 dark:text-white ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 placeholder:text-zinc-500 dark:placeholder:text-zinc-400 focus:ring-2 focus:ring-inset focus:ring-indigo-500 dark:focus:ring-indigo-400\"\n placeholder=\"admin@example.com\"\n />\n </div>\n\n <div>\n <label class=\"block text-sm/6 font-medium text-zinc-950 dark:text-white mb-2\">Timezone</label>\n <select\n name=\"timezone\"\n class=\"w-full rounded-lg bg-white dark:bg-white/5 px-3 py-2 text-sm/6 text-zinc-950 dark:text-white ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 focus:ring-2 focus:ring-inset focus:ring-indigo-500 dark:focus:ring-indigo-400\"\n >\n <option value=\"UTC\" ${settings?.timezone === 'UTC' ? 'selected' : ''}>UTC</option>\n <option value=\"America/New_York\" ${settings?.timezone === 'America/New_York' ? 'selected' : ''}>Eastern Time</option>\n <option value=\"America/Chicago\" ${settings?.timezone === 'America/Chicago' ? 'selected' : ''}>Central Time</option>\n <option value=\"America/Denver\" ${settings?.timezone === 'America/Denver' ? 'selected' : ''}>Mountain Time</option>\n <option value=\"America/Los_Angeles\" ${settings?.timezone === 'America/Los_Angeles' ? 'selected' : ''}>Pacific Time</option>\n </select>\n </div>\n </div>\n\n <div class=\"space-y-4\">\n <div>\n <label class=\"block text-sm/6 font-medium text-zinc-950 dark:text-white mb-2\">Site Description</label>\n <textarea\n name=\"siteDescription\"\n rows=\"3\"\n class=\"w-full rounded-lg bg-white dark:bg-white/5 px-3 py-2 text-sm/6 text-zinc-950 dark:text-white ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 placeholder:text-zinc-500 dark:placeholder:text-zinc-400 focus:ring-2 focus:ring-inset focus:ring-indigo-500 dark:focus:ring-indigo-400\"\n placeholder=\"Describe your site...\"\n >${settings?.siteDescription || ''}</textarea>\n </div>\n\n <div>\n <label class=\"block text-sm/6 font-medium text-zinc-950 dark:text-white mb-2\">Language</label>\n <select\n name=\"language\"\n class=\"w-full rounded-lg bg-white dark:bg-white/5 px-3 py-2 text-sm/6 text-zinc-950 dark:text-white ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 focus:ring-2 focus:ring-inset focus:ring-indigo-500 dark:focus:ring-indigo-400\"\n >\n <option value=\"en\" ${settings?.language === 'en' ? 'selected' : ''}>English</option>\n <option value=\"es\" ${settings?.language === 'es' ? 'selected' : ''}>Spanish</option>\n <option value=\"fr\" ${settings?.language === 'fr' ? 'selected' : ''}>French</option>\n <option value=\"de\" ${settings?.language === 'de' ? 'selected' : ''}>German</option>\n </select>\n </div>\n \n <div class=\"flex gap-3\">\n <div class=\"flex h-6 shrink-0 items-center\">\n <div class=\"group grid size-4 grid-cols-1\">\n <input\n type=\"checkbox\"\n id=\"maintenanceMode\"\n name=\"maintenanceMode\"\n ${settings?.maintenanceMode ? 'checked' : ''}\n class=\"col-start-1 row-start-1 appearance-none rounded border border-zinc-950/10 dark:border-white/10 bg-white dark:bg-white/5 checked:border-indigo-500 checked:bg-indigo-500 indeterminate:border-indigo-500 indeterminate:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-500 disabled:border-zinc-950/5 dark:disabled:border-white/5 disabled:bg-zinc-950/10 dark:disabled:bg-white/10 disabled:checked:bg-zinc-950/10 dark:disabled:checked:bg-white/10 forced-colors:appearance-auto\"\n />\n <svg viewBox=\"0 0 14 14\" fill=\"none\" class=\"pointer-events-none col-start-1 row-start-1 size-3.5 self-center justify-self-center stroke-white group-has-[:disabled]:stroke-zinc-950/25 dark:group-has-[:disabled]:stroke-white/25\">\n <path d=\"M3 8L6 11L11 3.5\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"opacity-0 group-has-[:checked]:opacity-100\" />\n <path d=\"M3 7H11\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"opacity-0 group-has-[:indeterminate]:opacity-100\" />\n </svg>\n </div>\n </div>\n <div class=\"text-sm/6\">\n <label for=\"maintenanceMode\" class=\"font-medium text-zinc-950 dark:text-white\">\n Enable maintenance mode\n </label>\n </div>\n </div>\n </div>\n </div>\n\n <!-- Save Button -->\n <div class=\"mt-8 pt-6 border-t border-zinc-950/5 dark:border-white/10 flex justify-end\">\n <button\n onclick=\"saveGeneralSettings()\"\n class=\"inline-flex items-center justify-center rounded-lg bg-zinc-950 dark:bg-white px-3.5 py-2.5 text-sm font-semibold text-white dark:text-zinc-950 hover:bg-zinc-800 dark:hover:bg-zinc-100 transition-colors shadow-sm\"\n >\n <svg class=\"-ml-0.5 mr-1.5 h-5 w-5\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M5 13l4 4L19 7\"/>\n </svg>\n Save Changes\n </button>\n </div>\n </div>\n `\n}\n\nfunction renderAppearanceSettings(settings?: AppearanceSettings): string {\n return `\n <div class=\"space-y-6\">\n <!-- WIP Notice -->\n <div class=\"rounded-lg bg-blue-50 dark:bg-blue-950/20 p-6 ring-1 ring-inset ring-blue-600/20 dark:ring-blue-500/30\">\n <div class=\"flex items-start space-x-3\">\n <svg class=\"w-6 h-6 text-blue-600 dark:text-blue-400 mt-0.5 flex-shrink-0\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z\"/>\n </svg>\n <div class=\"flex-1\">\n <h4 class=\"text-base/7 font-semibold text-blue-900 dark:text-blue-300\">Work in Progress</h4>\n <p class=\"mt-1 text-sm/6 text-blue-700 dark:text-blue-200\">\n This settings section is currently under development and provided for reference and design feedback only. Changes made here will not be saved.\n </p>\n </div>\n </div>\n </div>\n\n <div>\n <h3 class=\"text-lg font-semibold text-white mb-4\">Appearance Settings</h3>\n <p class=\"text-gray-300 mb-6\">Customize the look and feel of your application.</p>\n </div>\n \n <div class=\"grid grid-cols-1 md:grid-cols-2 gap-6\">\n <div class=\"space-y-4\">\n <div>\n <label class=\"block text-sm font-medium text-gray-300 mb-2\">Theme</label>\n <div class=\"grid grid-cols-3 gap-3\">\n <label class=\"flex items-center space-x-2 p-3 bg-white/10 rounded-lg border border-white/20 cursor-pointer hover:bg-white/20 transition-colors\">\n <input \n type=\"radio\" \n name=\"theme\" \n value=\"light\"\n ${settings?.theme === 'light' ? 'checked' : ''}\n class=\"text-blue-600\"\n />\n <span class=\"text-sm text-gray-300\">Light</span>\n </label>\n <label class=\"flex items-center space-x-2 p-3 bg-white/10 rounded-lg border border-white/20 cursor-pointer hover:bg-white/20 transition-colors\">\n <input \n type=\"radio\" \n name=\"theme\" \n value=\"dark\"\n ${settings?.theme === 'dark' || !settings?.theme ? 'checked' : ''}\n class=\"text-blue-600\"\n />\n <span class=\"text-sm text-gray-300\">Dark</span>\n </label>\n <label class=\"flex items-center space-x-2 p-3 bg-white/10 rounded-lg border border-white/20 cursor-pointer hover:bg-white/20 transition-colors\">\n <input \n type=\"radio\" \n name=\"theme\" \n value=\"auto\"\n ${settings?.theme === 'auto' ? 'checked' : ''}\n class=\"text-blue-600\"\n />\n <span class=\"text-sm text-gray-300\">Auto</span>\n </label>\n </div>\n </div>\n \n <div>\n <label class=\"block text-sm font-medium text-gray-300 mb-2\">Primary Color</label>\n <div class=\"flex items-center space-x-3\">\n <input \n type=\"color\" \n name=\"primaryColor\"\n value=\"${settings?.primaryColor || '#465FFF'}\"\n class=\"w-12 h-10 bg-white/10 border border-white/20 rounded-lg cursor-pointer\"\n />\n <input \n type=\"text\" \n value=\"${settings?.primaryColor || '#465FFF'}\"\n class=\"flex-1 px-3 py-2 bg-white/10 border border-white/20 rounded-lg text-white placeholder-gray-400 focus:outline-none focus:ring-2 focus:ring-blue-500\"\n placeholder=\"#465FFF\"\n />\n </div>\n </div>\n \n <div>\n <label class=\"block text-sm font-medium text-gray-300 mb-2\">Logo URL</label>\n <input \n type=\"url\" \n name=\"logoUrl\"\n value=\"${settings?.logoUrl || ''}\"\n class=\"w-full px-3 py-2 bg-white/10 border border-white/20 rounded-lg text-white placeholder-gray-400 focus:outline-none focus:ring-2 focus:ring-blue-500\"\n placeholder=\"https://example.com/logo.png\"\n />\n </div>\n </div>\n \n <div class=\"space-y-4\">\n <div>\n <label class=\"block text-sm font-medium text-gray-300 mb-2\">Favicon URL</label>\n <input \n type=\"url\" \n name=\"favicon\"\n value=\"${settings?.favicon || ''}\"\n class=\"w-full px-3 py-2 bg-white/10 border border-white/20 rounded-lg text-white placeholder-gray-400 focus:outline-none focus:ring-2 focus:ring-blue-500\"\n placeholder=\"https://example.com/favicon.ico\"\n />\n </div>\n \n <div>\n <label class=\"block text-sm font-medium text-gray-300 mb-2\">Custom CSS</label>\n <textarea \n name=\"customCSS\"\n rows=\"6\"\n class=\"w-full px-3 py-2 bg-white/10 border border-white/20 rounded-lg text-white placeholder-gray-400 focus:outline-none focus:ring-2 focus:ring-blue-500 font-mono text-sm\"\n placeholder=\"/* Add your custom CSS here */\"\n >${settings?.customCSS || ''}</textarea>\n </div>\n </div>\n </div>\n\n <!-- Save Button (Disabled for WIP) -->\n <div class=\"mt-8 pt-6 border-t border-zinc-950/5 dark:border-white/10 flex justify-end\">\n <button\n disabled\n class=\"inline-flex items-center justify-center rounded-lg bg-zinc-950/50 dark:bg-white/50 px-3.5 py-2.5 text-sm font-semibold text-white/50 dark:text-zinc-950/50 cursor-not-allowed shadow-sm\"\n >\n <svg class=\"-ml-0.5 mr-1.5 h-5 w-5\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M5 13l4 4L19 7\"/>\n </svg>\n Save Changes\n </button>\n </div>\n </div>\n `\n}\n\nfunction renderSecuritySettings(settings?: SecuritySettings): string {\n return `\n <div class=\"space-y-6\">\n <!-- WIP Notice -->\n <div class=\"rounded-lg bg-blue-50 dark:bg-blue-950/20 p-6 ring-1 ring-inset ring-blue-600/20 dark:ring-blue-500/30\">\n <div class=\"flex items-start space-x-3\">\n <svg class=\"w-6 h-6 text-blue-600 dark:text-blue-400 mt-0.5 flex-shrink-0\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z\"/>\n </svg>\n <div class=\"flex-1\">\n <h4 class=\"text-base/7 font-semibold text-blue-900 dark:text-blue-300\">Work in Progress</h4>\n <p class=\"mt-1 text-sm/6 text-blue-700 dark:text-blue-200\">\n This settings section is currently under development and provided for reference and design feedback only. Changes made here will not be saved.\n </p>\n </div>\n </div>\n </div>\n\n <div>\n <h3 class=\"text-lg font-semibold text-white mb-4\">Security Settings</h3>\n <p class=\"text-gray-300 mb-6\">Configure security and authentication settings.</p>\n </div>\n \n <div class=\"grid grid-cols-1 md:grid-cols-2 gap-6\">\n <div class=\"space-y-5\">\n <div class=\"flex gap-3\">\n <div class=\"flex h-6 shrink-0 items-center\">\n <div class=\"group grid size-4 grid-cols-1\">\n <input\n type=\"checkbox\"\n id=\"twoFactorEnabled\"\n name=\"twoFactorEnabled\"\n ${settings?.twoFactorEnabled ? 'checked' : ''}\n class=\"col-start-1 row-start-1 appearance-none rounded border border-zinc-950/10 dark:border-white/10 bg-white dark:bg-white/5 checked:border-indigo-500 checked:bg-indigo-500 indeterminate:border-indigo-500 indeterminate:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-500 disabled:border-zinc-950/5 dark:disabled:border-white/5 disabled:bg-zinc-950/10 dark:disabled:bg-white/10 disabled:checked:bg-zinc-950/10 dark:disabled:checked:bg-white/10 forced-colors:appearance-auto\"\n />\n <svg viewBox=\"0 0 14 14\" fill=\"none\" class=\"pointer-events-none col-start-1 row-start-1 size-3.5 self-center justify-self-center stroke-white group-has-[:disabled]:stroke-zinc-950/25 dark:group-has-[:disabled]:stroke-white/25\">\n <path d=\"M3 8L6 11L11 3.5\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"opacity-0 group-has-[:checked]:opacity-100\" />\n <path d=\"M3 7H11\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"opacity-0 group-has-[:indeterminate]:opacity-100\" />\n </svg>\n </div>\n </div>\n <div class=\"text-sm/6\">\n <label for=\"twoFactorEnabled\" class=\"font-medium text-zinc-950 dark:text-white\">\n Enable Two-Factor Authentication\n </label>\n </div>\n </div>\n \n <div>\n <label class=\"block text-sm font-medium text-gray-300 mb-2\">Session Timeout (minutes)</label>\n <input \n type=\"number\" \n name=\"sessionTimeout\"\n value=\"${settings?.sessionTimeout || 30}\"\n min=\"5\"\n max=\"1440\"\n class=\"w-full px-3 py-2 bg-white/10 border border-white/20 rounded-lg text-white placeholder-gray-400 focus:outline-none focus:ring-2 focus:ring-blue-500\"\n />\n </div>\n \n <div>\n <label class=\"block text-sm font-medium text-gray-300 mb-2\">Password Requirements</label>\n <div class=\"space-y-3\">\n <div class=\"flex gap-3\">\n <div class=\"flex h-6 shrink-0 items-center\">\n <div class=\"group grid size-4 grid-cols-1\">\n <input\n type=\"checkbox\"\n id=\"requireUppercase\"\n name=\"requireUppercase\"\n ${settings?.passwordRequirements?.requireUppercase ? 'checked' : ''}\n class=\"col-start-1 row-start-1 appearance-none rounded border border-zinc-950/10 dark:border-white/10 bg-white dark:bg-white/5 checked:border-indigo-500 checked:bg-indigo-500 indeterminate:border-indigo-500 indeterminate:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-500 disabled:border-zinc-950/5 dark:disabled:border-white/5 disabled:bg-zinc-950/10 dark:disabled:bg-white/10 disabled:checked:bg-zinc-950/10 dark:disabled:checked:bg-white/10 forced-colors:appearance-auto\"\n />\n <svg viewBox=\"0 0 14 14\" fill=\"none\" class=\"pointer-events-none col-start-1 row-start-1 size-3.5 self-center justify-self-center stroke-white group-has-[:disabled]:stroke-zinc-950/25 dark:group-has-[:disabled]:stroke-white/25\">\n <path d=\"M3 8L6 11L11 3.5\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"opacity-0 group-has-[:checked]:opacity-100\" />\n <path d=\"M3 7H11\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"opacity-0 group-has-[:indeterminate]:opacity-100\" />\n </svg>\n </div>\n </div>\n <div class=\"text-sm/6\">\n <label for=\"requireUppercase\" class=\"font-medium text-zinc-950 dark:text-white\">Require uppercase letters</label>\n </div>\n </div>\n <div class=\"flex gap-3\">\n <div class=\"flex h-6 shrink-0 items-center\">\n <div class=\"group grid size-4 grid-cols-1\">\n <input\n type=\"checkbox\"\n id=\"requireNumbers\"\n name=\"requireNumbers\"\n ${settings?.passwordRequirements?.requireNumbers ? 'checked' : ''}\n class=\"col-start-1 row-start-1 appearance-none rounded border border-zinc-950/10 dark:border-white/10 bg-white dark:bg-white/5 checked:border-indigo-500 checked:bg-indigo-500 indeterminate:border-indigo-500 indeterminate:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-500 disabled:border-zinc-950/5 dark:disabled:border-white/5 disabled:bg-zinc-950/10 dark:disabled:bg-white/10 disabled:checked:bg-zinc-950/10 dark:disabled:checked:bg-white/10 forced-colors:appearance-auto\"\n />\n <svg viewBox=\"0 0 14 14\" fill=\"none\" class=\"pointer-events-none col-start-1 row-start-1 size-3.5 self-center justify-self-center stroke-white group-has-[:disabled]:stroke-zinc-950/25 dark:group-has-[:disabled]:stroke-white/25\">\n <path d=\"M3 8L6 11L11 3.5\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"opacity-0 group-has-[:checked]:opacity-100\" />\n <path d=\"M3 7H11\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"opacity-0 group-has-[:indeterminate]:opacity-100\" />\n </svg>\n </div>\n </div>\n <div class=\"text-sm/6\">\n <label for=\"requireNumbers\" class=\"font-medium text-zinc-950 dark:text-white\">Require numbers</label>\n </div>\n </div>\n <div class=\"flex gap-3\">\n <div class=\"flex h-6 shrink-0 items-center\">\n <div class=\"group grid size-4 grid-cols-1\">\n <input\n type=\"checkbox\"\n id=\"requireSymbols\"\n name=\"requireSymbols\"\n ${settings?.passwordRequirements?.requireSymbols ? 'checked' : ''}\n class=\"col-start-1 row-start-1 appearance-none rounded border border-zinc-950/10 dark:border-white/10 bg-white dark:bg-white/5 checked:border-indigo-500 checked:bg-indigo-500 indeterminate:border-indigo-500 indeterminate:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-500 disabled:border-zinc-950/5 dark:disabled:border-white/5 disabled:bg-zinc-950/10 dark:disabled:bg-white/10 disabled:checked:bg-zinc-950/10 dark:disabled:checked:bg-white/10 forced-colors:appearance-auto\"\n />\n <svg viewBox=\"0 0 14 14\" fill=\"none\" class=\"pointer-events-none col-start-1 row-start-1 size-3.5 self-center justify-self-center stroke-white group-has-[:disabled]:stroke-zinc-950/25 dark:group-has-[:disabled]:stroke-white/25\">\n <path d=\"M3 8L6 11L11 3.5\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"opacity-0 group-has-[:checked]:opacity-100\" />\n <path d=\"M3 7H11\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"opacity-0 group-has-[:indeterminate]:opacity-100\" />\n </svg>\n </div>\n </div>\n <div class=\"text-sm/6\">\n <label for=\"requireSymbols\" class=\"font-medium text-zinc-950 dark:text-white\">Require symbols</label>\n </div>\n </div>\n </div>\n </div>\n </div>\n \n <div class=\"space-y-4\">\n <div>\n <label class=\"block text-sm font-medium text-gray-300 mb-2\">Minimum Password Length</label>\n <input \n type=\"number\" \n name=\"minPasswordLength\"\n value=\"${settings?.passwordRequirements?.minLength || 8}\"\n min=\"6\"\n max=\"128\"\n class=\"w-full px-3 py-2 bg-white/10 border border-white/20 rounded-lg text-white placeholder-gray-400 focus:outline-none focus:ring-2 focus:ring-blue-500\"\n />\n </div>\n \n <div>\n <label class=\"block text-sm font-medium text-gray-300 mb-2\">IP Whitelist</label>\n <textarea \n name=\"ipWhitelist\"\n rows=\"4\"\n class=\"w-full px-3 py-2 bg-white/10 border border-white/20 rounded-lg text-white placeholder-gray-400 focus:outline-none focus:ring-2 focus:ring-blue-500\"\n placeholder=\"Enter IP addresses (one per line) 192.168.1.1 10.0.0.1\"\n >${settings?.ipWhitelist?.join('\\n') || ''}</textarea>\n <p class=\"text-xs text-gray-400 mt-1\">Leave empty to allow all IPs</p>\n </div>\n </div>\n </div>\n\n <!-- Save Button (Disabled for WIP) -->\n <div class=\"mt-8 pt-6 border-t border-zinc-950/5 dark:border-white/10 flex justify-end\">\n <button\n disabled\n class=\"inline-flex items-center justify-center rounded-lg bg-zinc-950/50 dark:bg-white/50 px-3.5 py-2.5 text-sm font-semibold text-white/50 dark:text-zinc-950/50 cursor-not-allowed shadow-sm\"\n >\n <svg class=\"-ml-0.5 mr-1.5 h-5 w-5\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M5 13l4 4L19 7\"/>\n </svg>\n Save Changes\n </button>\n </div>\n </div>\n `\n}\n\nfunction renderNotificationSettings(settings?: NotificationSettings): string {\n return `\n <div class=\"space-y-6\">\n <!-- WIP Notice -->\n <div class=\"rounded-lg bg-blue-50 dark:bg-blue-950/20 p-6 ring-1 ring-inset ring-blue-600/20 dark:ring-blue-500/30\">\n <div class=\"flex items-start space-x-3\">\n <svg class=\"w-6 h-6 text-blue-600 dark:text-blue-400 mt-0.5 flex-shrink-0\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z\"/>\n </svg>\n <div class=\"flex-1\">\n <h4 class=\"text-base/7 font-semibold text-blue-900 dark:text-blue-300\">Work in Progress</h4>\n <p class=\"mt-1 text-sm/6 text-blue-700 dark:text-blue-200\">\n This settings section is currently under development and provided for reference and design feedback only. Changes made here will not be saved.\n </p>\n </div>\n </div>\n </div>\n\n <div>\n <h3 class=\"text-lg font-semibold text-white mb-4\">Notification Settings</h3>\n <p class=\"text-gray-300 mb-6\">Configure how and when you receive notifications.</p>\n </div>\n \n <div class=\"grid grid-cols-1 md:grid-cols-2 gap-6\">\n <div class=\"space-y-4\">\n <div>\n <h4 class=\"text-md font-medium text-white mb-3\">Email Notifications</h4>\n <div class=\"space-y-5\">\n <div class=\"flex gap-3\">\n <div class=\"flex h-6 shrink-0 items-center\">\n <div class=\"group grid size-4 grid-cols-1\">\n <input\n type=\"checkbox\"\n id=\"emailNotifications\"\n name=\"emailNotifications\"\n ${settings?.emailNotifications ? 'checked' : ''}\n class=\"col-start-1 row-start-1 appearance-none rounded border border-zinc-950/10 dark:border-white/10 bg-white dark:bg-white/5 checked:border-indigo-500 checked:bg-indigo-500 indeterminate:border-indigo-500 indeterminate:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-500 disabled:border-zinc-950/5 dark:disabled:border-white/5 disabled:bg-zinc-950/10 dark:disabled:bg-white/10 disabled:checked:bg-zinc-950/10 dark:disabled:checked:bg-white/10 forced-colors:appearance-auto\"\n />\n <svg viewBox=\"0 0 14 14\" fill=\"none\" class=\"pointer-events-none col-start-1 row-start-1 size-3.5 self-center justify-self-center stroke-white group-has-[:disabled]:stroke-zinc-950/25 dark:group-has-[:disabled]:stroke-white/25\">\n <path d=\"M3 8L6 11L11 3.5\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"opacity-0 group-has-[:checked]:opacity-100\" />\n <path d=\"M3 7H11\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"opacity-0 group-has-[:indeterminate]:opacity-100\" />\n </svg>\n </div>\n </div>\n <div class=\"text-sm/6\">\n <label for=\"emailNotifications\" class=\"font-medium text-zinc-950 dark:text-white\">Enable email notifications</label>\n </div>\n </div>\n\n <div class=\"flex gap-3\">\n <div class=\"flex h-6 shrink-0 items-center\">\n <div class=\"group grid size-4 grid-cols-1\">\n <input\n type=\"checkbox\"\n id=\"contentUpdates\"\n name=\"contentUpdates\"\n ${settings?.contentUpdates ? 'checked' : ''}\n class=\"col-start-1 row-start-1 appearance-none rounded border border-zinc-950/10 dark:border-white/10 bg-white dark:bg-white/5 checked:border-indigo-500 checked:bg-indigo-500 indeterminate:border-indigo-500 indeterminate:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-500 disabled:border-zinc-950/5 dark:disabled:border-white/5 disabled:bg-zinc-950/10 dark:disabled:bg-white/10 disabled:checked:bg-zinc-950/10 dark:disabled:checked:bg-white/10 forced-colors:appearance-auto\"\n />\n <svg viewBox=\"0 0 14 14\" fill=\"none\" class=\"pointer-events-none col-start-1 row-start-1 size-3.5 self-center justify-self-center stroke-white group-has-[:disabled]:stroke-zinc-950/25 dark:group-has-[:disabled]:stroke-white/25\">\n <path d=\"M3 8L6 11L11 3.5\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"opacity-0 group-has-[:checked]:opacity-100\" />\n <path d=\"M3 7H11\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"opacity-0 group-has-[:indeterminate]:opacity-100\" />\n </svg>\n </div>\n </div>\n <div class=\"text-sm/6\">\n <label for=\"contentUpdates\" class=\"font-medium text-zinc-950 dark:text-white\">Content updates</label>\n </div>\n </div>\n\n <div class=\"flex gap-3\">\n <div class=\"flex h-6 shrink-0 items-center\">\n <div class=\"group grid size-4 grid-cols-1\">\n <input\n type=\"checkbox\"\n id=\"systemAlerts\"\n name=\"systemAlerts\"\n ${settings?.systemAlerts ? 'checked' : ''}\n class=\"col-start-1 row-start-1 appearance-none rounded border border-zinc-950/10 dark:border-white/10 bg-white dark:bg-white/5 checked:border-indigo-500 checked:bg-indigo-500 indeterminate:border-indigo-500 indeterminate:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-500 disabled:border-zinc-950/5 dark:disabled:border-white/5 disabled:bg-zinc-950/10 dark:disabled:bg-white/10 disabled:checked:bg-zinc-950/10 dark:disabled:checked:bg-white/10 forced-colors:appearance-auto\"\n />\n <svg viewBox=\"0 0 14 14\" fill=\"none\" class=\"pointer-events-none col-start-1 row-start-1 size-3.5 self-center justify-self-center stroke-white group-has-[:disabled]:stroke-zinc-950/25 dark:group-has-[:disabled]:stroke-white/25\">\n <path d=\"M3 8L6 11L11 3.5\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"opacity-0 group-has-[:checked]:opacity-100\" />\n <path d=\"M3 7H11\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"opacity-0 group-has-[:indeterminate]:opacity-100\" />\n </svg>\n </div>\n </div>\n <div class=\"text-sm/6\">\n <label for=\"systemAlerts\" class=\"font-medium text-zinc-950 dark:text-white\">System alerts</label>\n </div>\n </div>\n\n <div class=\"flex gap-3\">\n <div class=\"flex h-6 shrink-0 items-center\">\n <div class=\"group grid size-4 grid-cols-1\">\n <input\n type=\"checkbox\"\n id=\"userRegistrations\"\n name=\"userRegistrations\"\n ${settings?.userRegistrations ? 'checked' : ''}\n class=\"col-start-1 row-start-1 appearance-none rounded border border-zinc-950/10 dark:border-white/10 bg-white dark:bg-white/5 checked:border-indigo-500 checked:bg-indigo-500 indeterminate:border-indigo-500 indeterminate:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-500 disabled:border-zinc-950/5 dark:disabled:border-white/5 disabled:bg-zinc-950/10 dark:disabled:bg-white/10 disabled:checked:bg-zinc-950/10 dark:disabled:checked:bg-white/10 forced-colors:appearance-auto\"\n />\n <svg viewBox=\"0 0 14 14\" fill=\"none\" class=\"pointer-events-none col-start-1 row-start-1 size-3.5 self-center justify-self-center stroke-white group-has-[:disabled]:stroke-zinc-950/25 dark:group-has-[:disabled]:stroke-white/25\">\n <path d=\"M3 8L6 11L11 3.5\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"opacity-0 group-has-[:checked]:opacity-100\" />\n <path d=\"M3 7H11\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"opacity-0 group-has-[:indeterminate]:opacity-100\" />\n </svg>\n </div>\n </div>\n <div class=\"text-sm/6\">\n <label for=\"userRegistrations\" class=\"font-medium text-zinc-950 dark:text-white\">New user registrations</label>\n </div>\n </div>\n </div>\n </div>\n </div>\n \n <div class=\"space-y-4\">\n <div>\n <label class=\"block text-sm font-medium text-gray-300 mb-2\">Email Frequency</label>\n <select \n name=\"emailFrequency\"\n class=\"w-full px-3 py-2 bg-white/10 border border-white/20 rounded-lg text-white focus:outline-none focus:ring-2 focus:ring-blue-500\"\n >\n <option value=\"immediate\" ${settings?.emailFrequency === 'immediate' ? 'selected' : ''}>Immediate</option>\n <option value=\"daily\" ${settings?.emailFrequency === 'daily' ? 'selected' : ''}>Daily Digest</option>\n <option value=\"weekly\" ${settings?.emailFrequency === 'weekly' ? 'selected' : ''}>Weekly Digest</option>\n </select>\n </div>\n \n <div class=\"p-4 bg-blue-500/20 border border-blue-500/30 rounded-lg\">\n <div class=\"flex items-start space-x-3\">\n <svg class=\"w-5 h-5 text-blue-400 mt-0.5\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z\"/>\n </svg>\n <div>\n <h5 class=\"text-sm font-medium text-blue-300\">Notification Preferences</h5>\n <p class=\"text-xs text-blue-200 mt-1\">\n Critical system alerts will always be sent immediately regardless of your frequency setting.\n </p>\n </div>\n </div>\n </div>\n </div>\n </div>\n\n <!-- Save Button (Disabled for WIP) -->\n <div class=\"mt-8 pt-6 border-t border-zinc-950/5 dark:border-white/10 flex justify-end\">\n <button\n disabled\n class=\"inline-flex items-center justify-center rounded-lg bg-zinc-950/50 dark:bg-white/50 px-3.5 py-2.5 text-sm font-semibold text-white/50 dark:text-zinc-950/50 cursor-not-allowed shadow-sm\"\n >\n <svg class=\"-ml-0.5 mr-1.5 h-5 w-5\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M5 13l4 4L19 7\"/>\n </svg>\n Save Changes\n </button>\n </div>\n </div>\n `\n}\n\nfunction renderStorageSettings(settings?: StorageSettings): string {\n return `\n <div class=\"space-y-6\">\n <!-- WIP Notice -->\n <div class=\"rounded-lg bg-blue-50 dark:bg-blue-950/20 p-6 ring-1 ring-inset ring-blue-600/20 dark:ring-blue-500/30\">\n <div class=\"flex items-start space-x-3\">\n <svg class=\"w-6 h-6 text-blue-600 dark:text-blue-400 mt-0.5 flex-shrink-0\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z\"/>\n </svg>\n <div class=\"flex-1\">\n <h4 class=\"text-base/7 font-semibold text-blue-900 dark:text-blue-300\">Work in Progress</h4>\n <p class=\"mt-1 text-sm/6 text-blue-700 dark:text-blue-200\">\n This settings section is currently under development and provided for reference and design feedback only. Changes made here will not be saved.\n </p>\n </div>\n </div>\n </div>\n\n <div>\n <h3 class=\"text-lg font-semibold text-white mb-4\">Storage Settings</h3>\n <p class=\"text-gray-300 mb-6\">Configure file storage and backup settings.</p>\n </div>\n \n <div class=\"grid grid-cols-1 md:grid-cols-2 gap-6\">\n <div class=\"space-y-4\">\n <div>\n <label class=\"block text-sm font-medium text-gray-300 mb-2\">Max File Size (MB)</label>\n <input \n type=\"number\" \n name=\"maxFileSize\"\n value=\"${settings?.maxFileSize || 10}\"\n min=\"1\"\n max=\"100\"\n class=\"w-full px-3 py-2 bg-white/10 border border-white/20 rounded-lg text-white placeholder-gray-400 focus:outline-none focus:ring-2 focus:ring-blue-500\"\n />\n </div>\n \n <div>\n <label class=\"block text-sm font-medium text-gray-300 mb-2\">Storage Provider</label>\n <select \n name=\"storageProvider\"\n class=\"w-full px-3 py-2 bg-white/10 border border-white/20 rounded-lg text-white focus:outline-none focus:ring-2 focus:ring-blue-500\"\n >\n <option value=\"local\" ${settings?.storageProvider === 'local' ? 'selected' : ''}>Local Storage</option>\n <option value=\"cloudflare\" ${settings?.storageProvider === 'cloudflare' ? 'selected' : ''}>Cloudflare R2</option>\n <option value=\"s3\" ${settings?.storageProvider === 's3' ? 'selected' : ''}>Amazon S3</option>\n </select>\n </div>\n \n <div>\n <label class=\"block text-sm font-medium text-gray-300 mb-2\">Backup Frequency</label>\n <select \n name=\"backupFrequency\"\n class=\"w-full px-3 py-2 bg-white/10 border border-white/20 rounded-lg text-white focus:outline-none focus:ring-2 focus:ring-blue-500\"\n >\n <option value=\"daily\" ${settings?.backupFrequency === 'daily' ? 'selected' : ''}>Daily</option>\n <option value=\"weekly\" ${settings?.backupFrequency === 'weekly' ? 'selected' : ''}>Weekly</option>\n <option value=\"monthly\" ${settings?.backupFrequency === 'monthly' ? 'selected' : ''}>Monthly</option>\n </select>\n </div>\n </div>\n \n <div class=\"space-y-4\">\n <div>\n <label class=\"block text-sm font-medium text-gray-300 mb-2\">Allowed File Types</label>\n <textarea \n name=\"allowedFileTypes\"\n rows=\"3\"\n class=\"w-full px-3 py-2 bg-white/10 border border-white/20 rounded-lg text-white placeholder-gray-400 focus:outline-none focus:ring-2 focus:ring-blue-500\"\n placeholder=\"jpg, jpeg, png, gif, pdf, docx\"\n >${settings?.allowedFileTypes?.join(', ') || 'jpg, jpeg, png, gif, pdf, docx'}</textarea>\n </div>\n \n <div>\n <label class=\"block text-sm font-medium text-gray-300 mb-2\">Backup Retention (days)</label>\n <input \n type=\"number\" \n name=\"retentionPeriod\"\n value=\"${settings?.retentionPeriod || 30}\"\n min=\"7\"\n max=\"365\"\n class=\"w-full px-3 py-2 bg-white/10 border border-white/20 rounded-lg text-white placeholder-gray-400 focus:outline-none focus:ring-2 focus:ring-blue-500\"\n />\n </div>\n \n <div class=\"p-4 bg-green-500/20 border border-green-500/30 rounded-lg\">\n <div class=\"flex items-start space-x-3\">\n <svg class=\"w-5 h-5 text-green-400 mt-0.5\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z\"/>\n </svg>\n <div>\n <h5 class=\"text-sm font-medium text-green-300\">Storage Status</h5>\n <p class=\"text-xs text-green-200 mt-1\">\n Current usage: 2.4 GB / 10 GB available\n </p>\n </div>\n </div>\n </div>\n </div>\n </div>\n\n <!-- Save Button (Disabled for WIP) -->\n <div class=\"mt-8 pt-6 border-t border-zinc-950/5 dark:border-white/10 flex justify-end\">\n <button\n disabled\n class=\"inline-flex items-center justify-center rounded-lg bg-zinc-950/50 dark:bg-white/50 px-3.5 py-2.5 text-sm font-semibold text-white/50 dark:text-zinc-950/50 cursor-not-allowed shadow-sm\"\n >\n <svg class=\"-ml-0.5 mr-1.5 h-5 w-5\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M5 13l4 4L19 7\"/>\n </svg>\n Save Changes\n </button>\n </div>\n </div>\n `\n}\n\nfunction renderMigrationSettings(settings?: MigrationSettings): string {\n return `\n <div class=\"space-y-6\">\n <div>\n <h3 class=\"text-lg font-semibold text-white mb-4\">Database Migrations</h3>\n <p class=\"text-gray-300 mb-6\">View and manage database migrations to keep your schema up to date.</p>\n </div>\n \n <!-- Migration Status Overview -->\n <div class=\"grid grid-cols-1 md:grid-cols-3 gap-4 mb-6\">\n <div class=\"backdrop-blur-md bg-blue-500/20 rounded-lg border border-blue-500/30 p-4\">\n <div class=\"flex items-center justify-between\">\n <div>\n <p class=\"text-sm text-blue-300\">Total Migrations</p>\n <p id=\"total-migrations\" class=\"text-2xl font-bold text-white\">${settings?.totalMigrations || '0'}</p>\n </div>\n <svg class=\"w-8 h-8 text-blue-400\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M4 7v10c0 2.21 3.582 4 8 4s8-1.79 8-4V7M4 7c0 2.21 3.582 4 8 4s8-1.79 8-4M4 7c0-2.21 3.582-4 8-4s8 1.79 8 4\"/>\n </svg>\n </div>\n </div>\n \n <div class=\"backdrop-blur-md bg-green-500/20 rounded-lg border border-green-500/30 p-4\">\n <div class=\"flex items-center justify-between\">\n <div>\n <p class=\"text-sm text-green-300\">Applied</p>\n <p id=\"applied-migrations\" class=\"text-2xl font-bold text-white\">${settings?.appliedMigrations || '0'}</p>\n </div>\n <svg class=\"w-8 h-8 text-green-400\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z\"/>\n </svg>\n </div>\n </div>\n \n <div class=\"backdrop-blur-md bg-orange-500/20 rounded-lg border border-orange-500/30 p-4\">\n <div class=\"flex items-center justify-between\">\n <div>\n <p class=\"text-sm text-orange-300\">Pending</p>\n <p id=\"pending-migrations\" class=\"text-2xl font-bold text-white\">${settings?.pendingMigrations || '0'}</p>\n </div>\n <svg class=\"w-8 h-8 text-orange-400\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z\"/>\n </svg>\n </div>\n </div>\n </div>\n\n <!-- Migration Actions -->\n <div class=\"flex items-center space-x-4 mb-6\">\n <button \n onclick=\"window.refreshMigrationStatus()\"\n class=\"inline-flex items-center px-4 py-2 bg-blue-600 hover:bg-blue-700 text-white text-sm font-medium rounded-lg transition-colors\"\n >\n <svg class=\"w-4 h-4 mr-2\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15\"/>\n </svg>\n Refresh Status\n </button>\n \n <button \n onclick=\"window.runPendingMigrations()\"\n id=\"run-migrations-btn\"\n class=\"inline-flex items-center px-4 py-2 bg-green-600 hover:bg-green-700 text-white text-sm font-medium rounded-lg transition-colors\"\n ${(settings?.pendingMigrations || 0) === 0 ? 'disabled' : ''}\n >\n <svg class=\"w-4 h-4 mr-2\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M14.828 14.828a4 4 0 01-5.656 0M9 10h1.586a1 1 0 01.707.293l2.414 2.414a1 1 0 00.707.293H15M9 10v4.586a1 1 0 00.293.707l2.414 2.414a1 1 0 00.707.293H15M9 10V9a2 2 0 012-2h2a2 2 0 012 2v1\"/>\n </svg>\n Run Pending\n </button>\n\n <button \n onclick=\"window.validateSchema()\" \n class=\"inline-flex items-center px-4 py-2 bg-purple-600 hover:bg-purple-700 text-white text-sm font-medium rounded-lg transition-colors\"\n >\n <svg class=\"w-4 h-4 mr-2\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z\"/>\n </svg>\n Validate Schema\n </button>\n </div>\n\n <!-- Migrations List -->\n <div class=\"backdrop-blur-md bg-white/10 rounded-lg border border-white/20 overflow-hidden\">\n <div class=\"px-6 py-4 border-b border-white/10\">\n <h4 class=\"text-lg font-medium text-white\">Migration History</h4>\n <p class=\"text-sm text-gray-300 mt-1\">List of all available database migrations</p>\n </div>\n \n <div id=\"migrations-list\" class=\"divide-y divide-white/10\">\n <div class=\"px-6 py-8 text-center\">\n <svg class=\"w-12 h-12 text-gray-400 mx-auto mb-4\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M4 7v10c0 2.21 3.582 4 8 4s8-1.79 8-4V7M4 7c0 2.21 3.582 4 8 4s8-1.79 8-4M4 7c0-2.21 3.582-4 8-4s8 1.79 8 4\"/>\n </svg>\n <p class=\"text-gray-300\">Loading migration status...</p>\n </div>\n </div>\n </div>\n </div>\n\n <script>\n // Load migration status when tab becomes active\n if (typeof refreshMigrationStatus === 'undefined') {\n window.refreshMigrationStatus = async function() {\n try {\n const response = await fetch('/admin/settings/api/migrations/status');\n const result = await response.json();\n \n if (result.success) {\n updateMigrationUI(result.data);\n } else {\n console.error('Failed to refresh migration status');\n }\n } catch (error) {\n console.error('Error loading migration status:', error);\n }\n };\n\n window.runPendingMigrations = async function() {\n const btn = document.getElementById('run-migrations-btn');\n if (!btn || btn.disabled) return;\n\n showConfirmDialog('run-migrations-confirm');\n };\n\n window.performRunMigrations = async function() {\n const btn = document.getElementById('run-migrations-btn');\n if (!btn) return;\n\n btn.disabled = true;\n btn.innerHTML = 'Running...';\n\n try {\n const response = await fetch('/admin/settings/api/migrations/run', {\n method: 'POST'\n });\n const result = await response.json();\n\n if (result.success) {\n alert(result.message);\n setTimeout(() => window.refreshMigrationStatus(), 1000);\n } else {\n alert(result.error || 'Failed to run migrations');\n }\n } catch (error) {\n alert('Error running migrations');\n } finally {\n btn.disabled = false;\n btn.innerHTML = 'Run Pending';\n }\n };\n\n window.validateSchema = async function() {\n try {\n const response = await fetch('/admin/settings/api/migrations/validate');\n const result = await response.json();\n \n if (result.success) {\n if (result.data.valid) {\n alert('Database schema is valid');\n } else {\n alert(\\`Schema validation failed: \\${result.data.issues.join(', ')}\\`);\n }\n } else {\n alert('Failed to validate schema');\n }\n } catch (error) {\n alert('Error validating schema');\n }\n };\n\n window.updateMigrationUI = function(data) {\n const totalEl = document.getElementById('total-migrations');\n const appliedEl = document.getElementById('applied-migrations');\n const pendingEl = document.getElementById('pending-migrations');\n \n if (totalEl) totalEl.textContent = data.totalMigrations;\n if (appliedEl) appliedEl.textContent = data.appliedMigrations;\n if (pendingEl) pendingEl.textContent = data.pendingMigrations;\n \n const runBtn = document.getElementById('run-migrations-btn');\n if (runBtn) {\n runBtn.disabled = data.pendingMigrations === 0;\n }\n \n // Update migrations list\n const listContainer = document.getElementById('migrations-list');\n if (listContainer && data.migrations && data.migrations.length > 0) {\n listContainer.innerHTML = data.migrations.map(migration => \\`\n <div class=\"px-6 py-4 flex items-center justify-between\">\n <div class=\"flex-1\">\n <div class=\"flex items-center space-x-3\">\n <div class=\"flex-shrink-0\">\n \\${migration.applied \n ? '<svg class=\"w-5 h-5 text-green-400\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\"><path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z\"/></svg>'\n : '<svg class=\"w-5 h-5 text-orange-400\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\"><path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z\"/></svg>'\n }\n </div>\n <div>\n <h5 class=\"text-white font-medium\">\\${migration.name}</h5>\n <p class=\"text-sm text-gray-300\">\\${migration.filename}</p>\n \\${migration.description ? \\`<p class=\"text-xs text-gray-400 mt-1\">\\${migration.description}</p>\\` : ''}\n </div>\n </div>\n </div>\n \n <div class=\"flex items-center space-x-4 text-sm\">\n \\${migration.size ? \\`<span class=\"text-gray-400\">\\${(migration.size / 1024).toFixed(1)} KB</span>\\` : ''}\n <span class=\"px-2 py-1 rounded-full text-xs font-medium \\${\n migration.applied \n ? 'bg-green-100 text-green-800' \n : 'bg-orange-100 text-orange-800'\n }\">\n \\${migration.applied ? 'Applied' : 'Pending'}\n </span>\n \\${migration.appliedAt ? \\`<span class=\"text-gray-400\">\\${new Date(migration.appliedAt).toLocaleDateString()}</span>\\` : ''}\n </div>\n </div>\n \\`).join('');\n }\n };\n }\n \n // Auto-load when tab becomes active\n if (currentTab === 'migrations') {\n setTimeout(refreshMigrationStatus, 500);\n }\n </script>\n `\n}\n\nfunction renderDatabaseToolsSettings(settings?: DatabaseToolsSettings): string {\n return `\n <div class=\"space-y-6\">\n <div>\n <h3 class=\"text-lg/7 font-semibold text-zinc-950 dark:text-white\">Database Tools</h3>\n <p class=\"mt-1 text-sm/6 text-zinc-500 dark:text-zinc-400\">Manage database operations including backup, restore, and maintenance.</p>\n </div>\n\n <!-- Database Statistics -->\n <div class=\"grid grid-cols-1 md:grid-cols-2 gap-4 mb-6\">\n <div class=\"rounded-lg bg-white dark:bg-white/5 p-6 ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10\">\n <div class=\"flex items-center justify-between\">\n <div>\n <p class=\"text-sm/6 font-medium text-zinc-500 dark:text-zinc-400\">Total Tables</p>\n <p id=\"total-tables\" class=\"mt-2 text-3xl/8 font-semibold text-zinc-950 dark:text-white\">${settings?.totalTables || '0'}</p>\n </div>\n <div class=\"rounded-lg bg-indigo-500/10 p-3\">\n <svg class=\"w-8 h-8 text-indigo-600 dark:text-indigo-400\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M19 11H5m14 0a2 2 0 012 2v6a2 2 0 01-2 2H5a2 2 0 01-2-2v-6a2 2 0 012-2m14 0V9a2 2 0 00-2-2M5 9a2 2 0 012-2m0 0V5a2 2 0 012-2h6a2 2 0 012 2v2M7 7h10\"/>\n </svg>\n </div>\n </div>\n </div>\n\n <div class=\"rounded-lg bg-white dark:bg-white/5 p-6 ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10\">\n <div class=\"flex items-center justify-between\">\n <div>\n <p class=\"text-sm/6 font-medium text-zinc-500 dark:text-zinc-400\">Total Rows</p>\n <p id=\"total-rows\" class=\"mt-2 text-3xl/8 font-semibold text-zinc-950 dark:text-white\">${settings?.totalRows?.toLocaleString() || '0'}</p>\n </div>\n <div class=\"rounded-lg bg-green-500/10 p-3\">\n <svg class=\"w-8 h-8 text-green-600 dark:text-green-400\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M9 5H7a2 2 0 00-2 2v10a2 2 0 002 2h8a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-3 7h3m-3 4h3m-6-4h.01M9 16h.01\"/>\n </svg>\n </div>\n </div>\n </div>\n </div>\n\n <!-- Database Operations -->\n <div class=\"space-y-4\">\n <!-- Safe Operations -->\n <div class=\"rounded-lg bg-white dark:bg-white/5 p-6 ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10\">\n <h4 class=\"text-base/7 font-semibold text-zinc-950 dark:text-white mb-4\">Safe Operations</h4>\n <div class=\"flex flex-wrap gap-3\">\n <button\n onclick=\"window.refreshDatabaseStats()\"\n class=\"inline-flex items-center justify-center rounded-lg bg-white dark:bg-zinc-800 px-3.5 py-2.5 text-sm font-semibold text-zinc-950 dark:text-white ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 hover:bg-zinc-50 dark:hover:bg-zinc-700 transition-colors shadow-sm\"\n >\n <svg class=\"-ml-0.5 mr-1.5 h-5 w-5\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15\"/>\n </svg>\n Refresh Stats\n </button>\n\n <button\n onclick=\"window.createDatabaseBackup()\"\n id=\"create-backup-btn\"\n class=\"inline-flex items-center justify-center rounded-lg bg-indigo-600 dark:bg-indigo-500 px-3.5 py-2.5 text-sm font-semibold text-white hover:bg-indigo-500 dark:hover:bg-indigo-400 transition-colors shadow-sm\"\n >\n <svg class=\"-ml-0.5 mr-1.5 h-5 w-5\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M12 10v6m0 0l-3-3m3 3l3-3m2 8H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z\"/>\n </svg>\n Create Backup\n </button>\n\n <button\n onclick=\"window.validateDatabase()\"\n class=\"inline-flex items-center justify-center rounded-lg bg-green-600 dark:bg-green-500 px-3.5 py-2.5 text-sm font-semibold text-white hover:bg-green-500 dark:hover:bg-green-400 transition-colors shadow-sm\"\n >\n <svg class=\"-ml-0.5 mr-1.5 h-5 w-5\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z\"/>\n </svg>\n Validate Database\n </button>\n </div>\n </div>\n </div>\n\n <!-- Tables List -->\n <div class=\"rounded-lg bg-white dark:bg-white/5 ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 overflow-hidden\">\n <div class=\"px-6 py-4 border-b border-zinc-950/10 dark:border-white/10\">\n <h4 class=\"text-base/7 font-semibold text-zinc-950 dark:text-white\">Database Tables</h4>\n <p class=\"mt-1 text-sm/6 text-zinc-500 dark:text-zinc-400\">Click on a table to view its data</p>\n </div>\n\n <div id=\"tables-list\" class=\"p-6 space-y-2\">\n <div class=\"text-center py-8\">\n <svg class=\"w-12 h-12 text-zinc-400 dark:text-zinc-500 mx-auto mb-4\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M19 11H5m14 0a2 2 0 012 2v6a2 2 0 01-2 2H5a2 2 0 01-2-2v-6a2 2 0 012-2m14 0V9a2 2 0 00-2-2M5 9a2 2 0 012-2m0 0V5a2 2 0 012-2h6a2 2 0 012 2v2M7 7h10\"/>\n </svg>\n <p class=\"text-zinc-500 dark:text-zinc-400\">Loading database statistics...</p>\n </div>\n </div>\n </div>\n\n <!-- Danger Zone -->\n <div class=\"rounded-lg bg-red-50 dark:bg-red-950/20 p-6 ring-1 ring-inset ring-red-600/20 dark:ring-red-500/30\">\n <div class=\"flex items-start space-x-3\">\n <svg class=\"w-6 h-6 text-red-600 dark:text-red-500 mt-0.5 flex-shrink-0\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-2.5L13.732 4c-.77-.833-1.964-.833-2.732 0L4.268 16.5c-.77.833.192 2.5 1.732 2.5z\"/>\n </svg>\n <div class=\"flex-1\">\n <h4 class=\"text-base/7 font-semibold text-red-900 dark:text-red-400\">Danger Zone</h4>\n <p class=\"mt-1 text-sm/6 text-red-700 dark:text-red-300\">\n These operations are destructive and cannot be undone.\n <strong>Your admin account will be preserved</strong>, but all other data will be permanently deleted.\n </p>\n <div class=\"mt-4\">\n <button\n onclick=\"window.truncateDatabase()\"\n id=\"truncate-db-btn\"\n class=\"inline-flex items-center justify-center rounded-lg bg-red-600 dark:bg-red-500 px-3.5 py-2.5 text-sm font-semibold text-white hover:bg-red-500 dark:hover:bg-red-400 transition-colors shadow-sm\"\n >\n <svg class=\"-ml-0.5 mr-1.5 h-5 w-5\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16\"/>\n </svg>\n Truncate All Data\n </button>\n </div>\n </div>\n </div>\n </div>\n </div>\n `\n}","import { Hono } from 'hono'\n// import { html } from 'hono/html'\nimport { requireAuth } from '../middleware'\nimport { renderSettingsPage, SettingsPageData } from '../templates/pages/admin-settings.template'\nimport { MigrationService } from '../services/migrations'\nimport { SettingsService } from '../services/settings'\n\ntype Bindings = {\n DB: D1Database\n CACHE_KV: KVNamespace\n MEDIA_BUCKET: R2Bucket\n ASSETS: Fetcher\n EMAIL_QUEUE?: Queue\n SENDGRID_API_KEY?: string\n DEFAULT_FROM_EMAIL?: string\n IMAGES_ACCOUNT_ID?: string\n IMAGES_API_TOKEN?: string\n ENVIRONMENT?: string\n}\n\ntype Variables = {\n user?: {\n userId: string\n email: string\n role: string\n exp: number\n iat: number\n }\n requestId?: string\n startTime?: number\n appVersion?: string\n}\n\nexport const adminSettingsRoutes = new Hono<{ Bindings: Bindings; Variables: Variables }>()\n\n// Apply authentication middleware\nadminSettingsRoutes.use('*', requireAuth())\n\n// Helper function to get mock settings data\nfunction getMockSettings(user: any) {\n return {\n general: {\n siteName: 'SonicJS AI',\n siteDescription: 'A modern headless CMS powered by AI',\n adminEmail: user?.email || 'admin@example.com',\n timezone: 'UTC',\n language: 'en',\n maintenanceMode: false\n },\n appearance: {\n theme: 'dark' as const,\n primaryColor: '#465FFF',\n logoUrl: '',\n favicon: '',\n customCSS: ''\n },\n security: {\n twoFactorEnabled: false,\n sessionTimeout: 30,\n passwordRequirements: {\n minLength: 8,\n requireUppercase: true,\n requireNumbers: true,\n requireSymbols: false\n },\n ipWhitelist: []\n },\n notifications: {\n emailNotifications: true,\n contentUpdates: true,\n systemAlerts: true,\n userRegistrations: false,\n emailFrequency: 'immediate' as const\n },\n storage: {\n maxFileSize: 10,\n allowedFileTypes: ['jpg', 'jpeg', 'png', 'gif', 'pdf', 'docx'],\n storageProvider: 'cloudflare' as const,\n backupFrequency: 'daily' as const,\n retentionPeriod: 30\n },\n migrations: {\n totalMigrations: 0,\n appliedMigrations: 0,\n pendingMigrations: 0,\n lastApplied: undefined,\n migrations: []\n },\n databaseTools: {\n totalTables: 0,\n totalRows: 0,\n lastBackup: undefined,\n databaseSize: '0 MB',\n tables: []\n }\n }\n}\n\n// Settings page (redirects to general settings)\nadminSettingsRoutes.get('/', (c) => {\n return c.redirect('/admin/settings/general')\n})\n\n// General settings\nadminSettingsRoutes.get('/general', async (c) => {\n const user = c.get('user')\n const db = c.env.DB\n const settingsService = new SettingsService(db)\n\n // Get real general settings from database\n const generalSettings = await settingsService.getGeneralSettings(user?.email)\n\n const mockSettings = getMockSettings(user)\n mockSettings.general = generalSettings\n\n const pageData: SettingsPageData = {\n user: user ? {\n name: user.email,\n email: user.email,\n role: user.role\n } : undefined,\n settings: mockSettings,\n activeTab: 'general',\n version: c.get('appVersion')\n }\n return c.html(renderSettingsPage(pageData))\n})\n\n// Appearance settings\nadminSettingsRoutes.get('/appearance', (c) => {\n const user = c.get('user')\n const pageData: SettingsPageData = {\n user: user ? {\n name: user.email,\n email: user.email,\n role: user.role\n } : undefined,\n settings: getMockSettings(user),\n activeTab: 'appearance',\n version: c.get('appVersion')\n }\n return c.html(renderSettingsPage(pageData))\n})\n\n// Security settings\nadminSettingsRoutes.get('/security', (c) => {\n const user = c.get('user')\n const pageData: SettingsPageData = {\n user: user ? {\n name: user.email,\n email: user.email,\n role: user.role\n } : undefined,\n settings: getMockSettings(user),\n activeTab: 'security',\n version: c.get('appVersion')\n }\n return c.html(renderSettingsPage(pageData))\n})\n\n// Notifications settings\nadminSettingsRoutes.get('/notifications', (c) => {\n const user = c.get('user')\n const pageData: SettingsPageData = {\n user: user ? {\n name: user.email,\n email: user.email,\n role: user.role\n } : undefined,\n settings: getMockSettings(user),\n activeTab: 'notifications',\n version: c.get('appVersion')\n }\n return c.html(renderSettingsPage(pageData))\n})\n\n// Storage settings\nadminSettingsRoutes.get('/storage', (c) => {\n const user = c.get('user')\n const pageData: SettingsPageData = {\n user: user ? {\n name: user.email,\n email: user.email,\n role: user.role\n } : undefined,\n settings: getMockSettings(user),\n activeTab: 'storage',\n version: c.get('appVersion')\n }\n return c.html(renderSettingsPage(pageData))\n})\n\n// Migrations settings\nadminSettingsRoutes.get('/migrations', (c) => {\n const user = c.get('user')\n const pageData: SettingsPageData = {\n user: user ? {\n name: user.email,\n email: user.email,\n role: user.role\n } : undefined,\n settings: getMockSettings(user),\n activeTab: 'migrations',\n version: c.get('appVersion')\n }\n return c.html(renderSettingsPage(pageData))\n})\n\n// Database tools settings\nadminSettingsRoutes.get('/database-tools', (c) => {\n const user = c.get('user')\n const pageData: SettingsPageData = {\n user: user ? {\n name: user.email,\n email: user.email,\n role: user.role\n } : undefined,\n settings: getMockSettings(user),\n activeTab: 'database-tools',\n version: c.get('appVersion')\n }\n return c.html(renderSettingsPage(pageData))\n})\n\n// Get migration status\nadminSettingsRoutes.get('/api/migrations/status', async (c) => {\n try {\n const db = c.env.DB\n const migrationService = new MigrationService(db)\n const status = await migrationService.getMigrationStatus()\n\n return c.json({\n success: true,\n data: status\n })\n } catch (error) {\n console.error('Error fetching migration status:', error)\n return c.json({\n success: false,\n error: 'Failed to fetch migration status'\n }, 500)\n }\n})\n\n// Run pending migrations\nadminSettingsRoutes.post('/api/migrations/run', async (c) => {\n try {\n const user = c.get('user')\n\n // Only allow admin users to run migrations\n if (!user || user.role !== 'admin') {\n return c.json({\n success: false,\n error: 'Unauthorized. Admin access required.'\n }, 403)\n }\n\n const db = c.env.DB\n const migrationService = new MigrationService(db)\n const result = await migrationService.runPendingMigrations()\n\n return c.json({\n success: result.success,\n message: result.message,\n applied: result.applied\n })\n } catch (error) {\n console.error('Error running migrations:', error)\n return c.json({\n success: false,\n error: 'Failed to run migrations'\n }, 500)\n }\n})\n\n// Validate database schema\nadminSettingsRoutes.get('/api/migrations/validate', async (c) => {\n try {\n const db = c.env.DB\n const migrationService = new MigrationService(db)\n const validation = await migrationService.validateSchema()\n\n return c.json({\n success: true,\n data: validation\n })\n } catch (error) {\n console.error('Error validating schema:', error)\n return c.json({\n success: false,\n error: 'Failed to validate schema'\n }, 500)\n }\n})\n\n// Get database tools stats\nadminSettingsRoutes.get('/api/database-tools/stats', async (c) => {\n try {\n const db = c.env.DB\n\n // Get list of all tables\n const tablesQuery = await db.prepare(`\n SELECT name FROM sqlite_master\n WHERE type='table'\n AND name NOT LIKE 'sqlite_%'\n AND name NOT LIKE '_cf_%'\n ORDER BY name\n `).all()\n\n const tables = tablesQuery.results || []\n let totalRows = 0\n\n // Get row count for each table\n const tableStats = await Promise.all(\n tables.map(async (table: any) => {\n try {\n const countResult = await db.prepare(`SELECT COUNT(*) as count FROM ${table.name}`).first()\n const rowCount = (countResult as any)?.count || 0\n totalRows += rowCount\n return {\n name: table.name,\n rowCount\n }\n } catch (error) {\n console.error(`Error counting rows in ${table.name}:`, error)\n return {\n name: table.name,\n rowCount: 0\n }\n }\n })\n )\n\n // D1 doesn't expose database size directly, so we'll estimate based on row counts\n // Average row size estimate: 1KB per row (rough approximation)\n const estimatedSizeBytes = totalRows * 1024\n const databaseSizeMB = (estimatedSizeBytes / (1024 * 1024)).toFixed(2)\n\n return c.json({\n success: true,\n data: {\n totalTables: tables.length,\n totalRows,\n databaseSize: `${databaseSizeMB} MB (estimated)`,\n tables: tableStats\n }\n })\n } catch (error) {\n console.error('Error fetching database stats:', error)\n return c.json({\n success: false,\n error: 'Failed to fetch database statistics'\n }, 500)\n }\n})\n\n// Validate database\nadminSettingsRoutes.get('/api/database-tools/validate', async (c) => {\n try {\n const db = c.env.DB\n\n // Run PRAGMA integrity_check\n const integrityResult = await db.prepare('PRAGMA integrity_check').first()\n const isValid = (integrityResult as any)?.integrity_check === 'ok'\n\n return c.json({\n success: true,\n data: {\n valid: isValid,\n message: isValid ? 'Database integrity check passed' : 'Database integrity check failed'\n }\n })\n } catch (error) {\n console.error('Error validating database:', error)\n return c.json({\n success: false,\n error: 'Failed to validate database'\n }, 500)\n }\n})\n\n// Backup database\nadminSettingsRoutes.post('/api/database-tools/backup', async (c) => {\n try {\n const user = c.get('user')\n\n // Only allow admin users\n if (!user || user.role !== 'admin') {\n return c.json({\n success: false,\n error: 'Unauthorized. Admin access required.'\n }, 403)\n }\n\n // TODO: Implement actual backup functionality\n // For now, return success message\n return c.json({\n success: true,\n message: 'Database backup feature coming soon. Use Cloudflare Dashboard for backups.'\n })\n } catch (error) {\n console.error('Error creating backup:', error)\n return c.json({\n success: false,\n error: 'Failed to create backup'\n }, 500)\n }\n})\n\n// Truncate tables\nadminSettingsRoutes.post('/api/database-tools/truncate', async (c) => {\n try {\n const user = c.get('user')\n\n // Only allow admin users\n if (!user || user.role !== 'admin') {\n return c.json({\n success: false,\n error: 'Unauthorized. Admin access required.'\n }, 403)\n }\n\n const body = await c.req.json()\n const tablesToTruncate = body.tables || []\n\n if (!Array.isArray(tablesToTruncate) || tablesToTruncate.length === 0) {\n return c.json({\n success: false,\n error: 'No tables specified for truncation'\n }, 400)\n }\n\n const db = c.env.DB\n const results = []\n\n for (const tableName of tablesToTruncate) {\n try {\n await db.prepare(`DELETE FROM ${tableName}`).run()\n results.push({ table: tableName, success: true })\n } catch (error) {\n console.error(`Error truncating ${tableName}:`, error)\n results.push({ table: tableName, success: false, error: String(error) })\n }\n }\n\n return c.json({\n success: true,\n message: `Truncated ${results.filter(r => r.success).length} of ${tablesToTruncate.length} tables`,\n results\n })\n } catch (error) {\n console.error('Error truncating tables:', error)\n return c.json({\n success: false,\n error: 'Failed to truncate tables'\n }, 500)\n }\n})\n\n// Save general settings\nadminSettingsRoutes.post('/general', async (c) => {\n try {\n const user = c.get('user')\n\n if (!user || user.role !== 'admin') {\n return c.json({\n success: false,\n error: 'Unauthorized. Admin access required.'\n }, 403)\n }\n\n const formData = await c.req.formData()\n const db = c.env.DB\n const settingsService = new SettingsService(db)\n\n // Extract general settings from form data\n const settings = {\n siteName: formData.get('siteName') as string,\n siteDescription: formData.get('siteDescription') as string,\n adminEmail: formData.get('adminEmail') as string,\n timezone: formData.get('timezone') as string,\n language: formData.get('language') as string,\n maintenanceMode: formData.get('maintenanceMode') === 'true'\n }\n\n // Validate required fields\n if (!settings.siteName || !settings.siteDescription) {\n return c.json({\n success: false,\n error: 'Site name and description are required'\n }, 400)\n }\n\n // Save settings to database\n const success = await settingsService.saveGeneralSettings(settings)\n\n if (success) {\n return c.json({\n success: true,\n message: 'General settings saved successfully!'\n })\n } else {\n return c.json({\n success: false,\n error: 'Failed to save settings'\n }, 500)\n }\n } catch (error) {\n console.error('Error saving general settings:', error)\n return c.json({\n success: false,\n error: 'Failed to save settings. Please try again.'\n }, 500)\n }\n})\n\n// Save settings (legacy endpoint - redirect to general)\nadminSettingsRoutes.post('/', async (c) => {\n return c.redirect('/admin/settings/general')\n})\n","/**\n * Routes Module Exports\n *\n * Routes are being migrated incrementally from the monolith.\n * Each route is refactored to remove monolith-specific dependencies.\n */\n\n// API routes\nexport { default as apiRoutes } from './api'\nexport { default as apiContentCrudRoutes } from './api-content-crud'\nexport { default as apiMediaRoutes } from './api-media'\nexport { default as apiSystemRoutes } from './api-system'\nexport { default as adminApiRoutes } from './admin-api'\n\n// Auth routes\nexport { default as authRoutes } from './auth'\n\n// Test routes (only for development/test environments)\nexport { default as testCleanupRoutes } from './test-cleanup'\n\n// Admin UI routes\nexport { default as adminContentRoutes } from './admin-content'\nexport { userRoutes as adminUsersRoutes } from './admin-users'\nexport { adminMediaRoutes } from './admin-media'\nexport { adminPluginRoutes } from './admin-plugins'\nexport { adminLogsRoutes } from './admin-logs'\nexport { adminDesignRoutes } from './admin-design'\nexport { adminCheckboxRoutes } from './admin-checkboxes'\nexport { default as adminTestimonialsRoutes } from './admin-testimonials'\nexport { default as adminCodeExamplesRoutes } from './admin-code-examples'\nexport { adminDashboardRoutes } from './admin-dashboard'\nexport { adminCollectionsRoutes } from './admin-collections'\nexport { adminSettingsRoutes } from './admin-settings'\n\nexport const ROUTES_INFO = {\n message: 'Core routes available',\n available: [\n 'apiRoutes',\n 'apiContentCrudRoutes',\n 'apiMediaRoutes',\n 'apiSystemRoutes',\n 'adminApiRoutes',\n 'authRoutes',\n 'testCleanupRoutes',\n 'adminContentRoutes',\n 'adminUsersRoutes',\n 'adminMediaRoutes',\n 'adminPluginRoutes',\n 'adminLogsRoutes',\n 'adminDesignRoutes',\n 'adminCheckboxRoutes',\n 'adminTestimonialsRoutes',\n 'adminCodeExamplesRoutes',\n 'adminDashboardRoutes',\n 'adminCollectionsRoutes',\n 'adminSettingsRoutes'\n ],\n status: 'Core package routes ready',\n reference: 'https://github.com/sonicjs/sonicjs'\n} as const\n"]}
|