@sonicjs-cms/core 2.0.1 → 2.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/dist/{chunk-SRCY43RN.cjs → chunk-3NVJ6W27.cjs} +2 -2
  2. package/dist/chunk-3NVJ6W27.cjs.map +1 -0
  3. package/dist/chunk-4BJGEGX5.cjs +236 -0
  4. package/dist/chunk-4BJGEGX5.cjs.map +1 -0
  5. package/dist/{chunk-5FDDDD4J.cjs → chunk-7G6XT62S.cjs} +321 -311
  6. package/dist/chunk-7G6XT62S.cjs.map +1 -0
  7. package/dist/chunk-ALOS2CBJ.cjs.map +1 -1
  8. package/dist/chunk-CDBVZEWR.js.map +1 -1
  9. package/dist/{chunk-BITQ4MFX.js → chunk-EAELJXRV.js} +93 -115
  10. package/dist/chunk-EAELJXRV.js.map +1 -0
  11. package/dist/chunk-FICTAGD4.js +59 -0
  12. package/dist/chunk-FICTAGD4.js.map +1 -0
  13. package/dist/{chunk-FVMV5DKA.cjs → chunk-HJZOA2O5.cjs} +93 -115
  14. package/dist/chunk-HJZOA2O5.cjs.map +1 -0
  15. package/dist/chunk-LEG4KNFP.cjs.map +1 -1
  16. package/dist/{chunk-5XTB4FE5.js → chunk-LH4Z7QID.js} +2 -2
  17. package/dist/chunk-LH4Z7QID.js.map +1 -0
  18. package/dist/chunk-M6FPVS7E.js +214 -0
  19. package/dist/chunk-M6FPVS7E.js.map +1 -0
  20. package/dist/chunk-O46XKBFM.js.map +1 -1
  21. package/dist/chunk-RCQ2HIQD.cjs +61 -0
  22. package/dist/chunk-RCQ2HIQD.cjs.map +1 -0
  23. package/dist/{chunk-QSF34IYQ.js → chunk-SGGHTIWV.js} +218 -208
  24. package/dist/chunk-SGGHTIWV.js.map +1 -0
  25. package/dist/{chunk-NK6FN5R5.cjs → chunk-UL32L2KV.cjs} +3 -60
  26. package/dist/chunk-UL32L2KV.cjs.map +1 -0
  27. package/dist/{chunk-OL2OE3VJ.js → chunk-XJETEIRU.js} +4 -60
  28. package/dist/chunk-XJETEIRU.js.map +1 -0
  29. package/dist/index.cjs +134 -119
  30. package/dist/index.cjs.map +1 -1
  31. package/dist/index.js +16 -12
  32. package/dist/index.js.map +1 -1
  33. package/dist/middleware.cjs +26 -21
  34. package/dist/middleware.js +2 -1
  35. package/dist/plugins.cjs +7 -7
  36. package/dist/plugins.js +1 -1
  37. package/dist/routes.cjs +25 -24
  38. package/dist/routes.js +5 -4
  39. package/dist/services.cjs +7 -7
  40. package/dist/services.js +1 -1
  41. package/dist/utils.cjs +16 -15
  42. package/dist/utils.js +2 -1
  43. package/package.json +1 -1
  44. package/dist/chunk-5FDDDD4J.cjs.map +0 -1
  45. package/dist/chunk-5XTB4FE5.js.map +0 -1
  46. package/dist/chunk-BITQ4MFX.js.map +0 -1
  47. package/dist/chunk-FVMV5DKA.cjs.map +0 -1
  48. package/dist/chunk-KM4AJFXI.cjs +0 -101
  49. package/dist/chunk-KM4AJFXI.cjs.map +0 -1
  50. package/dist/chunk-NK6FN5R5.cjs.map +0 -1
  51. package/dist/chunk-OL2OE3VJ.js.map +0 -1
  52. package/dist/chunk-QSF34IYQ.js.map +0 -1
  53. package/dist/chunk-SRCY43RN.cjs.map +0 -1
  54. package/dist/chunk-TY3NHEBN.js +0 -80
  55. package/dist/chunk-TY3NHEBN.js.map +0 -1
@@ -1,8 +1,9 @@
1
- import { getCacheService, CACHE_CONFIGS, getLogger } from './chunk-5XTB4FE5.js';
2
- import { requireAuth, isPluginActive, requireRole, AuthManager, logActivity, requirePermission } from './chunk-TY3NHEBN.js';
1
+ import { getCacheService, CACHE_CONFIGS, getLogger } from './chunk-LH4Z7QID.js';
2
+ import { requireAuth, isPluginActive, requireRole, AuthManager, logActivity, requirePermission } from './chunk-M6FPVS7E.js';
3
3
  import { PluginService, MigrationService } from './chunk-CDBVZEWR.js';
4
4
  import { init_admin_layout_catalyst_template, renderDesignPage, renderCheckboxPage, renderFAQList, renderTestimonialsList, renderCodeExamplesList, renderAlert, renderTable, renderPagination, renderConfirmationDialog, getConfirmationDialogScript, renderAdminLayoutCatalyst, renderAdminLayout, adminLayoutV2, renderForm } from './chunk-O46XKBFM.js';
5
- import { QueryFilterBuilder, sanitizeInput, getCoreVersion, escapeHtml } from './chunk-OL2OE3VJ.js';
5
+ import { QueryFilterBuilder, sanitizeInput, getCoreVersion, escapeHtml } from './chunk-XJETEIRU.js';
6
+ import { metricsTracker } from './chunk-FICTAGD4.js';
6
7
  import { Hono } from 'hono';
7
8
  import { cors } from 'hono/cors';
8
9
  import { z } from 'zod';
@@ -4704,6 +4705,7 @@ var isPluginActive2 = () => false;
4704
4705
 
4705
4706
  // src/routes/admin-content.ts
4706
4707
  var adminContentRoutes = new Hono();
4708
+ adminContentRoutes.use("*", requireAuth());
4707
4709
  async function getCollectionFields(db, collectionId) {
4708
4710
  const cache = getCacheService(CACHE_CONFIGS.collection);
4709
4711
  return cache.getOrSet(
@@ -5836,170 +5838,157 @@ ${JSON.stringify(data, null, 2)}
5836
5838
  var admin_content_default = adminContentRoutes;
5837
5839
 
5838
5840
  // src/templates/pages/admin-profile.template.ts
5841
+ init_admin_layout_catalyst_template();
5839
5842
  function renderProfilePage(data) {
5840
5843
  const pageContent = `
5841
- <div class="w-full px-4 sm:px-6 lg:px-8 py-6">
5844
+ <div class="space-y-8">
5842
5845
  <!-- Header -->
5843
- <div class="flex flex-col sm:flex-row sm:items-center sm:justify-between mb-6">
5846
+ <div class="sm:flex sm:items-center sm:justify-between">
5844
5847
  <div>
5845
- <h1 class="text-2xl font-semibold text-white">User Profile</h1>
5846
- <p class="mt-2 text-sm text-gray-300">Manage your account settings and preferences</p>
5848
+ <h1 class="text-2xl/8 font-semibold text-zinc-950 dark:text-white sm:text-xl/8">User Profile</h1>
5849
+ <p class="mt-2 text-sm/6 text-zinc-500 dark:text-zinc-400">
5850
+ Manage your account settings and preferences
5851
+ </p>
5847
5852
  </div>
5848
5853
  </div>
5849
5854
 
5850
- <!-- Breadcrumb -->
5851
- <nav class="flex mb-6" aria-label="Breadcrumb">
5852
- <ol class="flex items-center space-x-3">
5853
- <li>
5854
- <a href="/admin" class="text-gray-300 hover:text-white transition-colors">
5855
- <svg class="h-5 w-5" fill="currentColor" viewBox="0 0 20 20">
5856
- <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"/>
5857
- </svg>
5858
- </a>
5859
- </li>
5860
- <li class="flex items-center">
5861
- <svg class="h-5 w-5 text-gray-400 mx-2" fill="currentColor" viewBox="0 0 20 20">
5862
- <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"/>
5863
- </svg>
5864
- <span class="text-sm font-medium text-gray-200">Profile</span>
5865
- </li>
5866
- </ol>
5867
- </nav>
5868
-
5869
5855
  <!-- Alert Messages -->
5870
5856
  ${data.error ? renderAlert({ type: "error", message: data.error, dismissible: true }) : ""}
5871
5857
  ${data.success ? renderAlert({ type: "success", message: data.success, dismissible: true }) : ""}
5872
5858
 
5873
5859
  <!-- Profile Form -->
5874
- <div class="grid grid-cols-1 lg:grid-cols-3 gap-6">
5860
+ <div class="grid grid-cols-1 lg:grid-cols-3 gap-8">
5875
5861
  <!-- Main Profile Form -->
5876
5862
  <div class="lg:col-span-2">
5877
- <div class="backdrop-blur-xl bg-white/10 rounded-3xl border border-white/20 shadow-2xl overflow-hidden">
5863
+ <div class="rounded-xl bg-white dark:bg-zinc-900 shadow-sm ring-1 ring-zinc-950/5 dark:ring-white/10">
5878
5864
  <!-- Form Header -->
5879
- <div class="relative px-8 py-6 border-b border-white/10">
5880
- <div class="absolute inset-0 bg-gradient-to-r from-blue-600/10 via-purple-600/10 to-pink-600/10"></div>
5881
- <div class="relative flex items-center gap-3">
5882
- <div class="w-12 h-12 rounded-xl bg-white/10 backdrop-blur-sm flex items-center justify-center">
5883
- <svg class="w-6 h-6 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
5865
+ <div class="px-6 py-5 border-b border-zinc-950/5 dark:border-white/5">
5866
+ <div class="flex items-center gap-x-3">
5867
+ <div class="flex h-10 w-10 items-center justify-center rounded-lg bg-zinc-950 dark:bg-white">
5868
+ <svg class="h-5 w-5 text-white dark:text-zinc-950" fill="none" stroke="currentColor" viewBox="0 0 24 24">
5884
5869
  <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"/>
5885
5870
  </svg>
5886
5871
  </div>
5887
5872
  <div>
5888
- <h2 class="text-xl font-semibold text-white">Profile Information</h2>
5889
- <p class="text-sm text-gray-300">Update your account details and preferences</p>
5873
+ <h2 class="text-base font-semibold text-zinc-950 dark:text-white">Profile Information</h2>
5874
+ <p class="text-sm text-zinc-500 dark:text-zinc-400">Update your account details</p>
5890
5875
  </div>
5891
5876
  </div>
5892
5877
  </div>
5893
5878
 
5894
5879
  <!-- Form Content -->
5895
- <form id="profile-form" hx-put="/admin/profile" hx-target="#form-messages" class="p-8 space-y-6">
5880
+ <form id="profile-form" hx-put="/admin/profile" hx-target="#form-messages" class="p-6 space-y-6">
5896
5881
  <div id="form-messages"></div>
5897
5882
 
5898
5883
  <!-- Basic Information -->
5899
5884
  <div class="grid grid-cols-1 md:grid-cols-2 gap-6">
5900
5885
  <div>
5901
- <label class="block text-sm font-medium text-gray-300 mb-2">First Name</label>
5902
- <input
5903
- type="text"
5904
- name="first_name"
5886
+ <label class="block text-sm font-medium text-zinc-950 dark:text-white mb-2">First Name</label>
5887
+ <input
5888
+ type="text"
5889
+ name="first_name"
5905
5890
  value="${data.profile.first_name}"
5906
5891
  required
5907
- class="w-full px-4 py-3 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 focus:ring-2 focus:ring-white/20 transition-all"
5892
+ 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"
5908
5893
  placeholder="Enter your first name"
5909
5894
  >
5910
5895
  </div>
5911
5896
  <div>
5912
- <label class="block text-sm font-medium text-gray-300 mb-2">Last Name</label>
5913
- <input
5914
- type="text"
5915
- name="last_name"
5897
+ <label class="block text-sm font-medium text-zinc-950 dark:text-white mb-2">Last Name</label>
5898
+ <input
5899
+ type="text"
5900
+ name="last_name"
5916
5901
  value="${data.profile.last_name}"
5917
5902
  required
5918
- class="w-full px-4 py-3 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 focus:ring-2 focus:ring-white/20 transition-all"
5903
+ 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"
5919
5904
  placeholder="Enter your last name"
5920
5905
  >
5921
5906
  </div>
5922
5907
  </div>
5923
5908
 
5924
5909
  <div>
5925
- <label class="block text-sm font-medium text-gray-300 mb-2">Username</label>
5926
- <input
5927
- type="text"
5928
- name="username"
5910
+ <label class="block text-sm font-medium text-zinc-950 dark:text-white mb-2">Username</label>
5911
+ <input
5912
+ type="text"
5913
+ name="username"
5929
5914
  value="${data.profile.username}"
5930
5915
  required
5931
- class="w-full px-4 py-3 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 focus:ring-2 focus:ring-white/20 transition-all"
5916
+ 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"
5932
5917
  placeholder="Enter your username"
5933
5918
  >
5934
5919
  </div>
5935
5920
 
5936
5921
  <div>
5937
- <label class="block text-sm font-medium text-gray-300 mb-2">Email Address</label>
5938
- <input
5939
- type="email"
5940
- name="email"
5922
+ <label class="block text-sm font-medium text-zinc-950 dark:text-white mb-2">Email Address</label>
5923
+ <input
5924
+ type="email"
5925
+ name="email"
5941
5926
  value="${data.profile.email}"
5942
5927
  required
5943
- class="w-full px-4 py-3 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 focus:ring-2 focus:ring-white/20 transition-all"
5928
+ 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"
5944
5929
  placeholder="Enter your email address"
5945
5930
  >
5946
5931
  </div>
5947
5932
 
5948
5933
  <div>
5949
- <label class="block text-sm font-medium text-gray-300 mb-2">Phone Number</label>
5950
- <input
5951
- type="tel"
5952
- name="phone"
5934
+ <label class="block text-sm font-medium text-zinc-950 dark:text-white mb-2">Phone Number</label>
5935
+ <input
5936
+ type="tel"
5937
+ name="phone"
5953
5938
  value="${data.profile.phone || ""}"
5954
- class="w-full px-4 py-3 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 focus:ring-2 focus:ring-white/20 transition-all"
5939
+ 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"
5955
5940
  placeholder="Enter your phone number"
5956
5941
  >
5957
5942
  </div>
5958
5943
 
5959
5944
  <div>
5960
- <label class="block text-sm font-medium text-gray-300 mb-2">Bio</label>
5961
- <textarea
5962
- name="bio"
5945
+ <label class="block text-sm font-medium text-zinc-950 dark:text-white mb-2">Bio</label>
5946
+ <textarea
5947
+ name="bio"
5963
5948
  rows="3"
5964
- class="w-full px-4 py-3 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 focus:ring-2 focus:ring-white/20 transition-all resize-none"
5949
+ 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"
5965
5950
  placeholder="Tell us about yourself..."
5966
5951
  >${data.profile.bio || ""}</textarea>
5967
5952
  </div>
5968
5953
 
5969
5954
  <!-- Preferences -->
5970
- <div class="pt-6 border-t border-white/10">
5971
- <h3 class="text-lg font-semibold text-white mb-4">Preferences</h3>
5972
-
5955
+ <div class="pt-6 border-t border-zinc-950/5 dark:border-white/5">
5956
+ <h3 class="text-base font-semibold text-zinc-950 dark:text-white mb-4">Preferences</h3>
5957
+
5973
5958
  <div class="grid grid-cols-1 md:grid-cols-2 gap-6">
5974
5959
  <div>
5975
- <label class="block text-sm font-medium text-gray-300 mb-2">Timezone</label>
5976
- <select
5977
- name="timezone"
5978
- class="w-full px-4 py-3 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 focus:ring-2 focus:ring-white/20 transition-all"
5979
- >
5980
- ${data.timezones.map((tz) => `
5981
- <option value="${tz.value}" ${tz.value === data.profile.timezone ? "selected" : ""}>${tz.label}</option>
5982
- `).join("")}
5983
- </select>
5960
+ <label for="timezone" class="block text-sm/6 font-medium text-zinc-950 dark:text-white mb-2">Timezone</label>
5961
+ <div class="grid grid-cols-1">
5962
+ <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">
5963
+ ${data.timezones.map((tz) => `
5964
+ <option value="${tz.value}" ${tz.value === data.profile.timezone ? "selected" : ""}>${tz.label}</option>
5965
+ `).join("")}
5966
+ </select>
5967
+ <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">
5968
+ <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" />
5969
+ </svg>
5970
+ </div>
5984
5971
  </div>
5985
5972
  <div>
5986
- <label class="block text-sm font-medium text-gray-300 mb-2">Language</label>
5987
- <select
5988
- name="language"
5989
- class="w-full px-4 py-3 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 focus:ring-2 focus:ring-white/20 transition-all"
5990
- >
5991
- ${data.languages.map((lang) => `
5992
- <option value="${lang.value}" ${lang.value === data.profile.language ? "selected" : ""}>${lang.label}</option>
5993
- `).join("")}
5994
- </select>
5973
+ <label for="language" class="block text-sm/6 font-medium text-zinc-950 dark:text-white mb-2">Language</label>
5974
+ <div class="grid grid-cols-1">
5975
+ <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">
5976
+ ${data.languages.map((lang) => `
5977
+ <option value="${lang.value}" ${lang.value === data.profile.language ? "selected" : ""}>${lang.label}</option>
5978
+ `).join("")}
5979
+ </select>
5980
+ <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">
5981
+ <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" />
5982
+ </svg>
5983
+ </div>
5995
5984
  </div>
5996
5985
  </div>
5997
5986
  </div>
5998
5987
 
5999
5988
  <!-- Notifications -->
6000
- <div class="pt-6 border-t border-white/10">
6001
- <h3 class="text-lg font-semibold text-white mb-4">Notifications</h3>
6002
-
5989
+ <div class="pt-6 border-t border-zinc-950/5 dark:border-white/5">
5990
+ <h3 class="text-base font-semibold text-zinc-950 dark:text-white mb-4">Notifications</h3>
5991
+
6003
5992
  <div class="space-y-5">
6004
5993
  <div class="flex gap-3">
6005
5994
  <div class="flex h-6 shrink-0 items-center">
@@ -6010,27 +5999,30 @@ function renderProfilePage(data) {
6010
5999
  name="email_notifications"
6011
6000
  value="1"
6012
6001
  ${data.profile.email_notifications ? "checked" : ""}
6013
- 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"
6002
+ 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"
6014
6003
  />
6015
6004
  <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">
6016
6005
  <path d="M3 8L6 11L11 3.5" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="opacity-0 group-has-[:checked]:opacity-100" />
6017
- <path d="M3 7H11" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="opacity-0 group-has-[:indeterminate]:opacity-100" />
6018
6006
  </svg>
6019
6007
  </div>
6020
6008
  </div>
6021
6009
  <div class="text-sm/6">
6022
6010
  <label for="email_notifications" class="font-medium text-zinc-950 dark:text-white">Email notifications</label>
6011
+ <p class="text-zinc-500 dark:text-zinc-400">Receive email updates about new features and product announcements.</p>
6023
6012
  </div>
6024
6013
  </div>
6025
6014
  </div>
6026
6015
  </div>
6027
6016
 
6028
6017
  <!-- Submit Button -->
6029
- <div class="pt-6 border-t border-white/10">
6030
- <button
6018
+ <div class="pt-6 border-t border-zinc-950/5 dark:border-white/5">
6019
+ <button
6031
6020
  type="submit"
6032
- class="w-full px-6 py-3 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-transparent transition-all"
6021
+ 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"
6033
6022
  >
6023
+ <svg class="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
6024
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"/>
6025
+ </svg>
6034
6026
  Update Profile
6035
6027
  </button>
6036
6028
  </div>
@@ -6041,86 +6033,96 @@ function renderProfilePage(data) {
6041
6033
  <!-- Profile Sidebar -->
6042
6034
  <div class="lg:col-span-1 space-y-6">
6043
6035
  <!-- Avatar -->
6044
- <div class="backdrop-blur-xl bg-white/10 rounded-xl border border-white/20 shadow-2xl p-6">
6045
- <h3 class="text-lg font-semibold text-white mb-4">Profile Picture</h3>
6046
-
6036
+ <div class="rounded-xl bg-white dark:bg-zinc-900 shadow-sm ring-1 ring-zinc-950/5 dark:ring-white/10 p-6">
6037
+ <h3 class="text-base font-semibold text-zinc-950 dark:text-white mb-4">Profile Picture</h3>
6038
+
6047
6039
  <div class="text-center">
6048
- <div class="w-24 h-24 rounded-full mx-auto mb-4 overflow-hidden bg-gradient-to-br from-blue-500 to-purple-600 flex items-center justify-center">
6040
+ <div 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">
6049
6041
  ${data.profile.avatar_url ? `<img src="${data.profile.avatar_url}" alt="Profile picture" class="w-full h-full object-cover">` : `<span class="text-2xl font-bold text-white">${data.profile.first_name.charAt(0)}${data.profile.last_name.charAt(0)}</span>`}
6050
6042
  </div>
6051
-
6043
+
6052
6044
  <form id="avatar-form" hx-post="/admin/profile/avatar" hx-target="#avatar-messages" hx-encoding="multipart/form-data">
6053
- <input
6054
- type="file"
6055
- name="avatar"
6045
+ <input
6046
+ type="file"
6047
+ name="avatar"
6056
6048
  accept="image/*"
6057
6049
  class="hidden"
6058
6050
  id="avatar-input"
6059
6051
  onchange="document.getElementById('avatar-form').dispatchEvent(new Event('submit'))"
6060
6052
  >
6061
- <label
6053
+ <label
6062
6054
  for="avatar-input"
6063
- class="inline-block px-4 py-2 bg-white/10 text-white rounded-xl border border-white/20 hover:bg-white/20 transition-all cursor-pointer"
6055
+ 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"
6064
6056
  >
6057
+ <svg class="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
6058
+ <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"/>
6059
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 13a3 3 0 11-6 0 3 3 0 016 0z"/>
6060
+ </svg>
6065
6061
  Change Picture
6066
6062
  </label>
6067
6063
  </form>
6068
-
6064
+
6069
6065
  <div id="avatar-messages" class="mt-3"></div>
6070
6066
  </div>
6071
6067
  </div>
6072
6068
 
6073
6069
  <!-- Account Info -->
6074
- <div class="backdrop-blur-xl bg-white/10 rounded-xl border border-white/20 shadow-2xl p-6">
6075
- <h3 class="text-lg font-semibold text-white mb-4">Account Information</h3>
6076
-
6077
- <div class="space-y-3 text-sm">
6070
+ <div class="rounded-xl bg-white dark:bg-zinc-900 shadow-sm ring-1 ring-zinc-950/5 dark:ring-white/10 p-6">
6071
+ <h3 class="text-base font-semibold text-zinc-950 dark:text-white mb-4">Account Information</h3>
6072
+
6073
+ <dl class="space-y-3 text-sm">
6078
6074
  <div>
6079
- <span class="text-gray-400">Role:</span>
6080
- <span class="text-white ml-2 capitalize">${data.profile.role}</span>
6075
+ <dt class="text-zinc-500 dark:text-zinc-400">Role</dt>
6076
+ <dd class="mt-1">
6077
+ <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">
6078
+ ${data.profile.role}
6079
+ </span>
6080
+ </dd>
6081
6081
  </div>
6082
6082
  <div>
6083
- <span class="text-gray-400">Member Since:</span>
6084
- <span class="text-white ml-2">${new Date(data.profile.created_at).toLocaleDateString()}</span>
6083
+ <dt class="text-zinc-500 dark:text-zinc-400">Member Since</dt>
6084
+ <dd class="mt-1 text-zinc-950 dark:text-white">${new Date(data.profile.created_at).toLocaleDateString()}</dd>
6085
6085
  </div>
6086
6086
  ${data.profile.last_login_at ? `
6087
6087
  <div>
6088
- <span class="text-gray-400">Last Login:</span>
6089
- <span class="text-white ml-2">${new Date(data.profile.last_login_at).toLocaleDateString()}</span>
6088
+ <dt class="text-zinc-500 dark:text-zinc-400">Last Login</dt>
6089
+ <dd class="mt-1 text-zinc-950 dark:text-white">${new Date(data.profile.last_login_at).toLocaleDateString()}</dd>
6090
6090
  </div>
6091
6091
  ` : ""}
6092
6092
  <div>
6093
- <span class="text-gray-400">Two-Factor Auth:</span>
6094
- <span class="text-white ml-2">${data.profile.two_factor_enabled ? "Enabled" : "Disabled"}</span>
6093
+ <dt class="text-zinc-500 dark:text-zinc-400">Two-Factor Auth</dt>
6094
+ <dd class="mt-1">
6095
+ ${data.profile.two_factor_enabled ? '<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>' : '<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>'}
6096
+ </dd>
6095
6097
  </div>
6096
- </div>
6098
+ </dl>
6097
6099
  </div>
6098
6100
 
6099
6101
  <!-- Security Actions -->
6100
- <div class="backdrop-blur-xl bg-white/10 rounded-xl border border-white/20 shadow-2xl p-6">
6101
- <h3 class="text-lg font-semibold text-white mb-4">Security</h3>
6102
-
6103
- <div class="space-y-3">
6104
- <button
6102
+ <div class="rounded-xl bg-white dark:bg-zinc-900 shadow-sm ring-1 ring-zinc-950/5 dark:ring-white/10 p-6">
6103
+ <h3 class="text-base font-semibold text-zinc-950 dark:text-white mb-4">Security</h3>
6104
+
6105
+ <div class="space-y-2">
6106
+ <button
6105
6107
  type="button"
6106
6108
  onclick="showChangePasswordModal()"
6107
- class="w-full text-left px-3 py-2 text-sm text-gray-300 hover:text-white hover:bg-white/10 rounded-xl transition-all"
6109
+ 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"
6108
6110
  >
6109
- <svg class="w-4 h-4 inline mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
6111
+ <svg class="w-4 h-4 text-zinc-500 dark:text-zinc-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
6110
6112
  <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"/>
6111
6113
  </svg>
6112
- Change Password
6114
+ <span class="font-medium">Change Password</span>
6113
6115
  </button>
6114
-
6115
- <button
6116
+
6117
+ <button
6116
6118
  type="button"
6117
6119
  onclick="toggle2FA()"
6118
- class="w-full text-left px-3 py-2 text-sm text-gray-300 hover:text-white hover:bg-white/10 rounded-xl transition-all"
6120
+ 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"
6119
6121
  >
6120
- <svg class="w-4 h-4 inline mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
6122
+ <svg class="w-4 h-4 text-zinc-500 dark:text-zinc-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
6121
6123
  <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"/>
6122
6124
  </svg>
6123
- ${data.profile.two_factor_enabled ? "Disable" : "Enable"} 2FA
6125
+ <span class="font-medium">${data.profile.two_factor_enabled ? "Disable" : "Enable"} 2FA</span>
6124
6126
  </button>
6125
6127
  </div>
6126
6128
  </div>
@@ -6129,67 +6131,73 @@ function renderProfilePage(data) {
6129
6131
  </div>
6130
6132
 
6131
6133
  <!-- Change Password Modal -->
6132
- <div id="password-modal" class="fixed inset-0 bg-black/50 backdrop-blur-sm flex items-center justify-center z-50 hidden">
6133
- <div class="backdrop-blur-xl bg-white/10 rounded-xl border border-white/20 shadow-2xl w-full max-w-md mx-4">
6134
- <div class="relative px-6 py-4 border-b border-white/10">
6135
- <div class="absolute inset-0 bg-gradient-to-r from-blue-600/10 via-purple-600/10 to-pink-600/10"></div>
6136
- <div class="relative flex items-center justify-between">
6137
- <h3 class="text-lg font-semibold text-white">Change Password</h3>
6138
- <button onclick="closePasswordModal()" class="text-gray-300 hover:text-white">
6139
- <svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
6134
+ <div id="password-modal" class="fixed inset-0 bg-zinc-950/50 backdrop-blur-sm flex items-center justify-center z-50 hidden">
6135
+ <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">
6136
+ <div class="px-6 py-5 border-b border-zinc-950/5 dark:border-white/5">
6137
+ <div class="flex items-center justify-between">
6138
+ <h3 class="text-base font-semibold text-zinc-950 dark:text-white">Change Password</h3>
6139
+ <button onclick="closePasswordModal()" class="text-zinc-500 dark:text-zinc-400 hover:text-zinc-950 dark:hover:text-white transition-colors">
6140
+ <svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
6140
6141
  <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"></path>
6141
6142
  </svg>
6142
6143
  </button>
6143
6144
  </div>
6144
6145
  </div>
6145
-
6146
+
6146
6147
  <form id="password-form" hx-post="/admin/profile/password" hx-target="#password-messages" class="p-6 space-y-4">
6147
6148
  <div id="password-messages"></div>
6148
-
6149
+
6149
6150
  <div>
6150
- <label class="block text-sm font-medium text-gray-300 mb-2">Current Password</label>
6151
- <input
6152
- type="password"
6153
- name="current_password"
6151
+ <label class="block text-sm font-medium text-zinc-950 dark:text-white mb-2">Current Password</label>
6152
+ <input
6153
+ type="password"
6154
+ name="current_password"
6154
6155
  required
6155
- class="w-full px-4 py-3 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 focus:ring-2 focus:ring-white/20 transition-all"
6156
+ 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"
6157
+ placeholder="Enter current password"
6156
6158
  >
6157
6159
  </div>
6158
6160
 
6159
6161
  <div>
6160
- <label class="block text-sm font-medium text-gray-300 mb-2">New Password</label>
6161
- <input
6162
- type="password"
6163
- name="new_password"
6162
+ <label class="block text-sm font-medium text-zinc-950 dark:text-white mb-2">New Password</label>
6163
+ <input
6164
+ type="password"
6165
+ name="new_password"
6164
6166
  required
6165
6167
  minlength="8"
6166
- class="w-full px-4 py-3 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 focus:ring-2 focus:ring-white/20 transition-all"
6168
+ 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"
6169
+ placeholder="Enter new password"
6167
6170
  >
6171
+ <p class="mt-1 text-xs text-zinc-500 dark:text-zinc-400">Must be at least 8 characters</p>
6168
6172
  </div>
6169
6173
 
6170
6174
  <div>
6171
- <label class="block text-sm font-medium text-gray-300 mb-2">Confirm New Password</label>
6172
- <input
6173
- type="password"
6174
- name="confirm_password"
6175
+ <label class="block text-sm font-medium text-zinc-950 dark:text-white mb-2">Confirm New Password</label>
6176
+ <input
6177
+ type="password"
6178
+ name="confirm_password"
6175
6179
  required
6176
6180
  minlength="8"
6177
- class="w-full px-4 py-3 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 focus:ring-2 focus:ring-white/20 transition-all"
6181
+ 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"
6182
+ placeholder="Confirm new password"
6178
6183
  >
6179
6184
  </div>
6180
6185
 
6181
- <div class="flex justify-end space-x-3 pt-4 border-t border-white/10">
6182
- <button
6183
- type="button"
6186
+ <div class="flex justify-end gap-x-3 pt-4 border-t border-zinc-950/5 dark:border-white/5">
6187
+ <button
6188
+ type="button"
6184
6189
  onclick="closePasswordModal()"
6185
- class="px-4 py-2 bg-white/10 text-white rounded-xl border border-white/20 hover:bg-white/20 transition-all"
6190
+ 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"
6186
6191
  >
6187
6192
  Cancel
6188
6193
  </button>
6189
- <button
6194
+ <button
6190
6195
  type="submit"
6191
- class="px-4 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"
6196
+ 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"
6192
6197
  >
6198
+ <svg class="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
6199
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"/>
6200
+ </svg>
6193
6201
  Update Password
6194
6202
  </button>
6195
6203
  </div>
@@ -6232,9 +6240,10 @@ function renderProfilePage(data) {
6232
6240
  pageTitle: "Profile",
6233
6241
  currentPath: "/admin/profile",
6234
6242
  user: data.user,
6243
+ version: data.version,
6235
6244
  content: pageContent
6236
6245
  };
6237
- return renderAdminLayout(layoutData);
6246
+ return renderAdminLayoutCatalyst(layoutData);
6238
6247
  }
6239
6248
 
6240
6249
  // src/templates/components/alert.template.ts
@@ -7653,6 +7662,9 @@ function renderUsersListPage(data) {
7653
7662
  // src/routes/admin-users.ts
7654
7663
  var userRoutes = new Hono();
7655
7664
  userRoutes.use("*", requireAuth());
7665
+ userRoutes.get("/", (c) => {
7666
+ return c.redirect("/admin/dashboard");
7667
+ });
7656
7668
  var TIMEZONES = [
7657
7669
  { value: "UTC", label: "UTC" },
7658
7670
  { value: "America/New_York", label: "Eastern Time" },
@@ -10133,6 +10145,7 @@ var fileValidationSchema2 = z.object({
10133
10145
  // 50MB max
10134
10146
  });
10135
10147
  var adminMediaRoutes = new Hono();
10148
+ adminMediaRoutes.use("*", requireAuth());
10136
10149
  adminMediaRoutes.get("/", async (c) => {
10137
10150
  try {
10138
10151
  const user = c.get("user");
@@ -12152,6 +12165,7 @@ function formatTimestamp(timestamp) {
12152
12165
 
12153
12166
  // src/routes/admin-plugins.ts
12154
12167
  var adminPluginRoutes = new Hono();
12168
+ adminPluginRoutes.use("*", requireAuth());
12155
12169
  adminPluginRoutes.get("/", async (c) => {
12156
12170
  try {
12157
12171
  const user = c.get("user");
@@ -13261,6 +13275,7 @@ function renderLogConfigPage(data) {
13261
13275
 
13262
13276
  // src/routes/admin-logs.ts
13263
13277
  var adminLogsRoutes = new Hono();
13278
+ adminLogsRoutes.use("*", requireAuth());
13264
13279
  adminLogsRoutes.get("/", async (c) => {
13265
13280
  try {
13266
13281
  const user = c.get("user");
@@ -15743,7 +15758,7 @@ function renderAnalyticsChart() {
15743
15758
 
15744
15759
  <!-- Hidden div to trigger HTMX polling -->
15745
15760
  <div
15746
- hx-get="/admin/api/metrics"
15761
+ hx-get="/admin/dashboard/api/metrics"
15747
15762
  hx-trigger="every 1s"
15748
15763
  hx-swap="none"
15749
15764
  style="display: none;"
@@ -15846,9 +15861,12 @@ function renderAnalyticsChart() {
15846
15861
 
15847
15862
  // Listen for metrics updates from HTMX
15848
15863
  window.addEventListener('htmx:afterRequest', function(event) {
15849
- if (event.detail.pathInfo.requestPath === '/admin/api/metrics') {
15864
+ console.log('[Dashboard] HTMX request completed:', event.detail.pathInfo.requestPath);
15865
+
15866
+ if (event.detail.pathInfo.requestPath === '/admin/dashboard/api/metrics') {
15850
15867
  try {
15851
15868
  const metrics = JSON.parse(event.detail.xhr.responseText);
15869
+ console.log('[Dashboard] Metrics received:', metrics);
15852
15870
 
15853
15871
  // Update current RPS display
15854
15872
  const rpsElement = document.getElementById('current-rps');
@@ -15869,8 +15887,9 @@ function renderAnalyticsChart() {
15869
15887
  chart.data.labels = newLabels;
15870
15888
 
15871
15889
  chart.update('none'); // Update without animation for smoother real-time updates
15890
+ console.log('[Dashboard] Chart updated with RPS:', metrics.requestsPerSecond);
15872
15891
  } catch (e) {
15873
- console.error('Error updating metrics:', e);
15892
+ console.error('[Dashboard] Error updating metrics:', e);
15874
15893
  }
15875
15894
  }
15876
15895
  });
@@ -16217,7 +16236,7 @@ router.get("/", async (c) => {
16217
16236
  return c.html(renderDashboardPage(pageData));
16218
16237
  }
16219
16238
  });
16220
- router.get("/dashboard/stats", async (c) => {
16239
+ router.get("/stats", async (c) => {
16221
16240
  try {
16222
16241
  const db = c.env.DB;
16223
16242
  let collectionsCount = 0;
@@ -16267,7 +16286,7 @@ router.get("/dashboard/stats", async (c) => {
16267
16286
  return c.html('<div class="text-red-500">Failed to load statistics</div>');
16268
16287
  }
16269
16288
  });
16270
- router.get("/dashboard/storage", async (c) => {
16289
+ router.get("/storage", async (c) => {
16271
16290
  try {
16272
16291
  const db = c.env.DB;
16273
16292
  let databaseSize = 0;
@@ -16292,7 +16311,7 @@ router.get("/dashboard/storage", async (c) => {
16292
16311
  return c.html('<div class="text-red-500">Failed to load storage information</div>');
16293
16312
  }
16294
16313
  });
16295
- router.get("/dashboard/recent-activity", async (c) => {
16314
+ router.get("/recent-activity", async (c) => {
16296
16315
  try {
16297
16316
  const db = c.env.DB;
16298
16317
  const limit = parseInt(c.req.query("limit") || "5");
@@ -16344,25 +16363,14 @@ router.get("/dashboard/recent-activity", async (c) => {
16344
16363
  }
16345
16364
  });
16346
16365
  router.get("/api/metrics", async (c) => {
16347
- try {
16348
- const { metricsTracker } = await import('../utils/metrics-tracker');
16349
- return c.json({
16350
- requestsPerSecond: metricsTracker.getRequestsPerSecond(),
16351
- totalRequests: metricsTracker.getTotalRequests(),
16352
- averageRPS: metricsTracker.getAverageRPS(),
16353
- timestamp: (/* @__PURE__ */ new Date()).toISOString()
16354
- });
16355
- } catch (error) {
16356
- console.error("Error fetching metrics:", error);
16357
- return c.json({
16358
- requestsPerSecond: 0,
16359
- totalRequests: 0,
16360
- averageRPS: 0,
16361
- timestamp: (/* @__PURE__ */ new Date()).toISOString()
16362
- });
16363
- }
16366
+ return c.json({
16367
+ requestsPerSecond: metricsTracker.getRequestsPerSecond(),
16368
+ totalRequests: metricsTracker.getTotalRequests(),
16369
+ averageRPS: Number(metricsTracker.getAverageRPS().toFixed(2)),
16370
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
16371
+ });
16364
16372
  });
16365
- router.get("/dashboard/system-status", async (c) => {
16373
+ router.get("/system-status", async (c) => {
16366
16374
  try {
16367
16375
  const html9 = `
16368
16376
  <div class="grid grid-cols-1 sm:grid-cols-2 gap-4">
@@ -17683,7 +17691,8 @@ function renderCollectionFormPage(data) {
17683
17691
 
17684
17692
  // src/routes/admin-collections.ts
17685
17693
  var adminCollectionsRoutes = new Hono();
17686
- adminCollectionsRoutes.get("/collections", async (c) => {
17694
+ adminCollectionsRoutes.use("*", requireAuth());
17695
+ adminCollectionsRoutes.get("/", async (c) => {
17687
17696
  try {
17688
17697
  const user = c.get("user");
17689
17698
  const db = c.env.DB;
@@ -17738,7 +17747,7 @@ adminCollectionsRoutes.get("/collections", async (c) => {
17738
17747
  return c.html(html`<p>Error loading collections</p>`);
17739
17748
  }
17740
17749
  });
17741
- adminCollectionsRoutes.get("/collections/new", (c) => {
17750
+ adminCollectionsRoutes.get("/new", (c) => {
17742
17751
  const user = c.get("user");
17743
17752
  const formData = {
17744
17753
  isEdit: false,
@@ -17751,7 +17760,7 @@ adminCollectionsRoutes.get("/collections/new", (c) => {
17751
17760
  };
17752
17761
  return c.html(renderCollectionFormPage(formData));
17753
17762
  });
17754
- adminCollectionsRoutes.post("/collections", async (c) => {
17763
+ adminCollectionsRoutes.post("/", async (c) => {
17755
17764
  try {
17756
17765
  const formData = await c.req.formData();
17757
17766
  const name = formData.get("name");
@@ -17870,7 +17879,7 @@ adminCollectionsRoutes.post("/collections", async (c) => {
17870
17879
  }
17871
17880
  }
17872
17881
  });
17873
- adminCollectionsRoutes.get("/collections/:id", async (c) => {
17882
+ adminCollectionsRoutes.get("/:id", async (c) => {
17874
17883
  try {
17875
17884
  const id = c.req.param("id");
17876
17885
  const user = c.get("user");
@@ -17938,7 +17947,7 @@ adminCollectionsRoutes.get("/collections/:id", async (c) => {
17938
17947
  return c.html(renderCollectionFormPage(formData));
17939
17948
  }
17940
17949
  });
17941
- adminCollectionsRoutes.put("/collections/:id", async (c) => {
17950
+ adminCollectionsRoutes.put("/:id", async (c) => {
17942
17951
  try {
17943
17952
  const id = c.req.param("id");
17944
17953
  const formData = await c.req.formData();
@@ -17972,7 +17981,7 @@ adminCollectionsRoutes.put("/collections/:id", async (c) => {
17972
17981
  `);
17973
17982
  }
17974
17983
  });
17975
- adminCollectionsRoutes.delete("/collections/:id", async (c) => {
17984
+ adminCollectionsRoutes.delete("/:id", async (c) => {
17976
17985
  try {
17977
17986
  const id = c.req.param("id");
17978
17987
  const db = c.env.DB;
@@ -18003,7 +18012,7 @@ adminCollectionsRoutes.delete("/collections/:id", async (c) => {
18003
18012
  `);
18004
18013
  }
18005
18014
  });
18006
- adminCollectionsRoutes.post("/collections/:id/fields", async (c) => {
18015
+ adminCollectionsRoutes.post("/:id/fields", async (c) => {
18007
18016
  try {
18008
18017
  const collectionId = c.req.param("id");
18009
18018
  const formData = await c.req.formData();
@@ -18056,7 +18065,7 @@ adminCollectionsRoutes.post("/collections/:id/fields", async (c) => {
18056
18065
  return c.json({ success: false, error: "Failed to add field." });
18057
18066
  }
18058
18067
  });
18059
- adminCollectionsRoutes.put("/collections/:collectionId/fields/:fieldId", async (c) => {
18068
+ adminCollectionsRoutes.put("/:collectionId/fields/:fieldId", async (c) => {
18060
18069
  try {
18061
18070
  const fieldId = c.req.param("fieldId");
18062
18071
  const formData = await c.req.formData();
@@ -18080,7 +18089,7 @@ adminCollectionsRoutes.put("/collections/:collectionId/fields/:fieldId", async (
18080
18089
  return c.json({ success: false, error: "Failed to update field." });
18081
18090
  }
18082
18091
  });
18083
- adminCollectionsRoutes.delete("/collections/:collectionId/fields/:fieldId", async (c) => {
18092
+ adminCollectionsRoutes.delete("/:collectionId/fields/:fieldId", async (c) => {
18084
18093
  try {
18085
18094
  const fieldId = c.req.param("fieldId");
18086
18095
  const db = c.env.DB;
@@ -18092,7 +18101,7 @@ adminCollectionsRoutes.delete("/collections/:collectionId/fields/:fieldId", asyn
18092
18101
  return c.json({ success: false, error: "Failed to delete field." });
18093
18102
  }
18094
18103
  });
18095
- adminCollectionsRoutes.post("/collections/:collectionId/fields/reorder", async (c) => {
18104
+ adminCollectionsRoutes.post("/:collectionId/fields/reorder", async (c) => {
18096
18105
  try {
18097
18106
  const body = await c.req.json();
18098
18107
  const fieldIds = body.fieldIds;
@@ -19539,6 +19548,7 @@ function renderDatabaseToolsSettings(settings) {
19539
19548
 
19540
19549
  // src/routes/admin-settings.ts
19541
19550
  var adminSettingsRoutes = new Hono();
19551
+ adminSettingsRoutes.use("*", requireAuth());
19542
19552
  function getMockSettings(user) {
19543
19553
  return {
19544
19554
  general: {
@@ -19597,10 +19607,10 @@ function getMockSettings(user) {
19597
19607
  }
19598
19608
  };
19599
19609
  }
19600
- adminSettingsRoutes.get("/settings", (c) => {
19610
+ adminSettingsRoutes.get("/", (c) => {
19601
19611
  return c.redirect("/admin/settings/general");
19602
19612
  });
19603
- adminSettingsRoutes.get("/settings/general", (c) => {
19613
+ adminSettingsRoutes.get("/general", (c) => {
19604
19614
  const user = c.get("user");
19605
19615
  const pageData = {
19606
19616
  user: user ? {
@@ -19614,7 +19624,7 @@ adminSettingsRoutes.get("/settings/general", (c) => {
19614
19624
  };
19615
19625
  return c.html(renderSettingsPage(pageData));
19616
19626
  });
19617
- adminSettingsRoutes.get("/settings/appearance", (c) => {
19627
+ adminSettingsRoutes.get("/appearance", (c) => {
19618
19628
  const user = c.get("user");
19619
19629
  const pageData = {
19620
19630
  user: user ? {
@@ -19628,7 +19638,7 @@ adminSettingsRoutes.get("/settings/appearance", (c) => {
19628
19638
  };
19629
19639
  return c.html(renderSettingsPage(pageData));
19630
19640
  });
19631
- adminSettingsRoutes.get("/settings/security", (c) => {
19641
+ adminSettingsRoutes.get("/security", (c) => {
19632
19642
  const user = c.get("user");
19633
19643
  const pageData = {
19634
19644
  user: user ? {
@@ -19642,7 +19652,7 @@ adminSettingsRoutes.get("/settings/security", (c) => {
19642
19652
  };
19643
19653
  return c.html(renderSettingsPage(pageData));
19644
19654
  });
19645
- adminSettingsRoutes.get("/settings/notifications", (c) => {
19655
+ adminSettingsRoutes.get("/notifications", (c) => {
19646
19656
  const user = c.get("user");
19647
19657
  const pageData = {
19648
19658
  user: user ? {
@@ -19656,7 +19666,7 @@ adminSettingsRoutes.get("/settings/notifications", (c) => {
19656
19666
  };
19657
19667
  return c.html(renderSettingsPage(pageData));
19658
19668
  });
19659
- adminSettingsRoutes.get("/settings/storage", (c) => {
19669
+ adminSettingsRoutes.get("/storage", (c) => {
19660
19670
  const user = c.get("user");
19661
19671
  const pageData = {
19662
19672
  user: user ? {
@@ -19670,7 +19680,7 @@ adminSettingsRoutes.get("/settings/storage", (c) => {
19670
19680
  };
19671
19681
  return c.html(renderSettingsPage(pageData));
19672
19682
  });
19673
- adminSettingsRoutes.get("/settings/migrations", (c) => {
19683
+ adminSettingsRoutes.get("/migrations", (c) => {
19674
19684
  const user = c.get("user");
19675
19685
  const pageData = {
19676
19686
  user: user ? {
@@ -19684,7 +19694,7 @@ adminSettingsRoutes.get("/settings/migrations", (c) => {
19684
19694
  };
19685
19695
  return c.html(renderSettingsPage(pageData));
19686
19696
  });
19687
- adminSettingsRoutes.get("/settings/database-tools", (c) => {
19697
+ adminSettingsRoutes.get("/database-tools", (c) => {
19688
19698
  const user = c.get("user");
19689
19699
  const pageData = {
19690
19700
  user: user ? {
@@ -19757,7 +19767,7 @@ adminSettingsRoutes.get("/api/migrations/validate", async (c) => {
19757
19767
  }, 500);
19758
19768
  }
19759
19769
  });
19760
- adminSettingsRoutes.post("/settings", async (c) => {
19770
+ adminSettingsRoutes.post("/", async (c) => {
19761
19771
  try {
19762
19772
  const formData = await c.req.formData();
19763
19773
  return c.html(html`
@@ -19809,5 +19819,5 @@ var ROUTES_INFO = {
19809
19819
  };
19810
19820
 
19811
19821
  export { ROUTES_INFO, adminCheckboxRoutes, adminCollectionsRoutes, adminDesignRoutes, adminLogsRoutes, adminMediaRoutes, adminPluginRoutes, adminSettingsRoutes, admin_api_default, admin_code_examples_default, admin_content_default, admin_faq_default, admin_testimonials_default, api_content_crud_default, api_default, api_media_default, api_system_default, auth_default, router, userRoutes };
19812
- //# sourceMappingURL=chunk-QSF34IYQ.js.map
19813
- //# sourceMappingURL=chunk-QSF34IYQ.js.map
19822
+ //# sourceMappingURL=chunk-SGGHTIWV.js.map
19823
+ //# sourceMappingURL=chunk-SGGHTIWV.js.map