@infuro/cms-core 1.0.14 → 1.0.16

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/admin.js CHANGED
@@ -1,13 +1,14 @@
1
1
  "use client";
2
2
 
3
3
  // src/admin/pages/AdminLayout.tsx
4
- import React5, { useEffect as useEffect2, useState as useState2 } from "react";
4
+ import React5, { useEffect as useEffect2, useState as useState3 } from "react";
5
5
  import { useSession as useSession2 } from "next-auth/react";
6
6
  import { useRouter, usePathname as usePathname3 } from "next/navigation";
7
7
  import { Toaster } from "sonner";
8
8
 
9
9
  // src/components/Admin/Header.tsx
10
10
  import { signOut, useSession } from "next-auth/react";
11
+ import { useMemo, useState as useState2 } from "react";
11
12
 
12
13
  // src/components/ui/button.tsx
13
14
  import * as React from "react";
@@ -229,25 +230,44 @@ function useIsMobile() {
229
230
  return !!isMobile;
230
231
  }
231
232
 
233
+ // src/lib/infuro-favicon.ts
234
+ var INFURO_FAVICON_BASE64 = "data:image/x-icon;base64,AAABAAMAEBAAAAEAIABoBAAANgAAACAgAAABACAAKBEAAJ4EAAAwMAAAAQAgAGgmAADGFQAAKAAAABAAAAAgAAAAAQAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///8V////bv///7D////R////0f///7D///9u////FQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///wL///9s0qun7q9qYv/DkYv/6tfV///+/v///////////////+7///9r////AgAAAAAAAAAAAAAAAP///wL///+Q/////sqcl/+WOzH/ljsx/5c9M//AiYP/+/j4/////////////////v///5D///8CAAAAAAAAAAD///9s/////v/////Oo5//lz00/5Y7Mf+WOzH/ljsx/7Z3cP/9+/v////////////////+////bAAAAAD///8V////7v///////////v39//Tq6f/QqKP/m0U8/5Y7Mf+WOzH/z6ah/////////////////////+7///8V////bv///////////////////////////////+XOy/+ZQTf/ljsx/59MQ//69fX/////////////////////bv///7D/////////////////////////////////////wYyG/5Y7Mf+WOzH/4MTC/////////////////////7D////R//////////////////7+//79/f/+/f3//v39/+DGw/+WOzH/ljsx/82inf/////////////////////R////0f///////////////9Svq/+mWVH/pllR/6ZZUf+iUUj/ljsx/5Y7Mf/KnJf/////////////////////0f///7D////////////////KnJf/ljsx/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/062p/////////////////////7D///9u////////////////0amk/6FQSP+hUEj/oVBI/6JRSP+mWVH/plpS/+7g3v////////////////////9u////Ff///+7///////////7+/v/9/Pz/9u7t/8SSjP/Dj4r/9ezr//79/f/////////////////////u////FQAAAAD///9s/////v///////////////8OPif+WOzH/ljsx/7+Jgv/////////////////////+////bAAAAAAAAAAA////Av///5D////+//////////+9hH7/ljsx/5Y7Mf+8g3z////////////////+////kP///wIAAAAAAAAAAAAAAAD///8C////bP///+7/////8OTi/7R0bP+zcmr/8OLh///////////u////bP///wIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///8V////bv///7D////R////0f///7D///9u////FQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKAAAACAAAABAAAAAAQAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///8C////Hf///0n///95////mf///67///+u////mf///3n///9J////Hf///wIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///8I////Tf///7D////p/////v////////////////////////////////////7////p////sP///03///8IAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///8C////Pfjz8r7HlpH7wY2H/86lof/iysf/9e3s///+/v//////////////////////////////////////////+////77///89////AgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////Cf///37////z9Ovq/6BORf+WOzH/ljsx/5Y8Mv+hUEf/v4iC/+rY1v/+/f3///////////////////////////////////////////H///99////CQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///wr///+d/////P/////06+r/oE5F/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/m0Q7/8WTjf/38PD///////////////////////////////////////////z///+d////CgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///8J////nf////3///////////Tr6v+gTkX/ljsx/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/61mX//w4+L///////////////////////////////////////////3///+d////CQAAAAAAAAAAAAAAAAAAAAAAAAAA////Av///37////8////////////////9Ovq/6BORf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/6daUv/v4uD///////////////////////////////////////////z///9+////AgAAAAAAAAAAAAAAAAAAAAD///89////8//////////////////////48fD/rGRc/5pCOf+YPjT/ljsx/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/6xkXf/37+////////////////////////////////////////////P///89AAAAAAAAAAAAAAAA////CP///77////////////////////////////////7+Pf/8eXj/+DGw/++hn//m0U8/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/8GLhf/9/Pz//////////////////////////////////////////77///8IAAAAAAAAAAD///9N////+/////////////////////////////////////////////////7+/v/p1tP/rGRd/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/mkI4/+XPzf//////////////////////////////////////////+////00AAAAA////Av///7D////////////////////////////////////////////////////////////////06+r/r2pi/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/tndw//38+///////////////////////////////////////////sP///wL///8d////6f/////////////////////////////////////////////////////////////////////x5eP/olJJ/5Y7Mf+WOzH/ljsx/5Y7Mf+aQjn/7dza///////////////////////////////////////////p////Hf///0n////+///////////////////////////////////////////////////////////////////////////Ur6v/ljwy/5Y7Mf+WOzH/ljsx/5Y7Mf/Oo5////////////////////////////////////////////7///9J////ef////////////////////////////////////////////////////////////////////////////////fw7/+jVEv/ljsx/5Y7Mf+WOzH/ljsx/7Nxav///////////////////////////////////////////////3n///+Z/////////////////////////////////////////////////////////////////////////////////////7yCfP+WOzH/ljsx/5Y7Mf+WOzH/pllQ//r29f//////////////////////////////////////////mf///67///////////////////////////////////////////79/f/9/Pz//fz8//38/P/9/Pz//fz8//38/P/9/Pz/yZuW/5Y7Mf+WOzH/ljsx/5Y7Mf+gT0b/9evr//////////////////////////////////////////+u////rv/////////////////////////////////////69vb/wo2I/7Z3cf+2d3H/tndx/7Z3cf+2d3H/tndx/7Z3cf+lV0//ljsx/5Y7Mf+WOzH/ljsx/6BORf/06+r//////////////////////////////////////////67///+Z//////////////////////////////////////Tr6v+gTkX/ljsx/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/oE5F//Tr6v//////////////////////////////////////////mf///3n/////////////////////////////////////9Ovq/6BORf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/5Y7Mf+lVk7/+fPz//////////////////////////////////////////95////Sf////7////////////////////////////////06+r/oE5F/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/7FuZ////v7//////////////////////////////////////v///0n///8d////6f////////////////////////////////Tr6v+gTkX/ljsx/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/zKCb///////////////////////////////////////////p////Hf///wL///+w////////////////////////////////+PLx/7d4cf+tZl//rWZf/61mX/+tZl//rWZf/61mX/+tZl//rmdg/7Z3cP+2d3H/tndx/7h7df/w4uH//////////////////////////////////////////7D///8CAAAAAP///03////7/////////////////////////////////Pv6//z6+f/8+vn//Pr5//z6+f/z6un/48zJ/+LKx//y5+b//fz8//38/P/9/Pz//fz8///////////////////////////////////////////7////TQAAAAAAAAAA////CP///77/////////////////////////////////////////////////////4MXC/6VXTv+WPDL/ljwy/6JRSP/aubb///7+/////////////////////////////////////////////////////77///8IAAAAAAAAAAAAAAAA////Pf////P///////////////////////////////////////////Xs6/+jU0r/ljsx/5Y7Mf+WOzH/ljsx/59MQv/w5OL////////////////////////////////////////////////z////PQAAAAAAAAAAAAAAAAAAAAD///8C////fv////z/////////////////////////////////////3sK//5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/9m5tf///////////////////////////////////////////P///37///8CAAAAAAAAAAAAAAAAAAAAAAAAAAD///8J////nf////3////////////////////////////////ZuLX/ljsx/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/17Sw//////////////////////////////////////3///+d////CQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///8K////nf////z//////////////////////////+zc2v+aQzn/ljsx/5Y7Mf+WOzH/ljsx/5pDOf/r2tj////////////////////////////////8////nf///woAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///8J////fv////P//////////////////////v39/8eYkv+YPjT/ljsx/5Y7Mf+YPjT/xpSP//79/f//////////////////////////8////37///8JAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///8C////Pf///77////7/////////////////fv6/+DEwf/Ekoz/wY2H/97Bvv/8+vr/////////////////////+////77///89////AgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////CP///03///+w////6f////7////////////////////////////////////+////6f///7D///9N////CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///wL///8d////Sf///3n///+Z////rv///67///+Z////ef///0n///8d////AgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKAAAADAAAABgAAAAAQAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///8E////DP///xr///80////Rv///1n///9q////gP///4D///9q////Wf///0b///80////Gv///wz///8EAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////CP///y7///9g////lP///7v////V////6P////r////8/////P////z////8////+v///+j////V////u////5T///9g////Lv///wgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///wf///81////k////8/////v////+v////////////////////////////////////////////////////////////////////r////v////z////5P///81////BwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///8G////Kv37+3zt3Nrd27y5/Nm6t//fxMH/59LQ//Dk4v/48vH//fv6//////////////////////////////////////////////////////////////////////z////d////fP///yr///8GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///xH///9g////wvz5+ffNop3+m0U8/5c+NP+cRz7/pFVN/65oYP+8gnv/0qun/+jU0v/59fT//v7+///////////////////////////////////////////////////////////+////9////8L///9f////EQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////GP///4n////m/////fv4+P/KnJf/mUE4/5Y7Mf+WOzH/ljsx/5Y7Mf+XPTT/m0Q6/6ZaUf/BjIX/6NXT//z5+f////////////////////////////////////////////////////////////////3////k////if///xgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///wH///8i////pP////f///////////v4+P/KnJf/mUE4/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/5Y7Mf+XPjT/oVFI/8yhnP/x5OP//vz8////////////////////////////////////////////////////////////////9////6T///8i////AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///yL///+d////8/////////////////v4+P/KnJf/mUE4/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/5tEOv+3eHL/48rH//37+/////////////////////////////////////////////////////////////////P///+d////IgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////GP///6T////z//////////////////////v4+P/KnJf/mUE4/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/5Y7Mf+YPjT/qFxT/9y+uv/9+vr////////////////////////////////////////////////////////////////z////pP///xgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///8R////if////f///////////////////////////v4+P/KnJf/mUE4/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljsy/6NUS//Yt7P//Pn4////////////////////////////////////////////////////////////////9////4n///8RAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///wb///9g////5v////////////////////////////////v4+P/KnZj/mUI4/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/5c8Mv+pXlb/38PA//38/P///////////////////////////////////////////////////////////////+b///9g////BgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///yr////C/////f////////////////////////////////38+//dwLz/qF1V/51JP/+bRDv/mD40/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/5Y7Mf+XPTP/qWBY/+vZ2P///v7///////////////////////////////////////////////////////////3////C////KgAAAAAAAAAAAAAAAAAAAAAAAAAA////B////3z////3///////////////////////////////////////////9+/r/9/Dv/+zc2f/dwLz/x5iT/7BrY/+eS0H/lz0z/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/lzwy/7d6c//06un////////////////////////////////////////////////////////////////3////fP///wcAAAAAAAAAAAAAAAAAAAAA////Nf///93////+//////////////////////////////////////////////////////7+/v/+/v7//fz8//Hm5f/XtLH/s3Fq/5lCOP+WOzH/ljsx/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/51JP//Sq6b//Pn5///////////////////////////////////////////////////////////+////3f///zUAAAAAAAAAAAAAAAD///8I////k/////z////////////////////////////////////////////////////////////////////////////////9+/v/8eTj/8aVkP+dRz7/ljsx/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/5c8Mv+vamL/7uDf/////////////////////////////////////////////////////////////////P///5P///8IAAAAAAAAAAD///8u////z/////////////////////////////////////////////////////////////////////////////////////////////////fx8P/ImZP/nUg//5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/5Y7Mf+ZQTj/0qyo//38/P///////////////////////////////////////////////////////////////8////8uAAAAAP///wT///9g////7//////////////////////////////////////////////////////////////////////////////////////////////////////07Or/xJGL/5hAN/+WOzH/ljsx/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/rGRd//Tq6P///////////////////////////////////////////////////////////////+////9g////BP///wz///+U////+v////////////////////////////////////////////////////////////////////////////////////////////////////////7/8+jm/7Nya/+WPDP/ljsx/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/mkQ7/9m3s////v7///////////////////////////////////////////////////////////r///+U////DP///xr///+7/////////////////////////////////////////////////////////////////////////////////////////////////////////////////v7+/+HHxP+hUEf/ljsx/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljwy/7yBe//69/f///////////////////////////////////////////////////////////////+7////Gv///zT////V//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////bu7f+7gHr/mD40/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/6xkXP/u4N/////////////////////////////////////////////////////////////////V////NP///0b////o//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////38/P/XtK//nEY9/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/6BNRP/iycb////////////////////////////////////////////////////////////////o////Rv///1n////6///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////o1NL/pVhQ/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/5xGPP/Yt7L//v39///////////////////////////////////////////////////////////6////Wf///2r////8///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////06un/sW1m/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/5pDOf/PpKD//Pr5///////////////////////////////////////////////////////////8////av///4D////8/////////////////////////////////////////////////////////////v7//fv7//37+v/9+/r//fv6//37+v/9+/r//fv6//37+v/9+/r//fv6//37+v/06un/snBp/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/5lBOP/KnJj/+/j4///////////////////////////////////////////////////////////8////gP///4D////8//////////////////////////////////////////////////////79/f/s3Nr/z6ej/8uemv/Lnpr/y56a/8uemv/Lnpr/y56a/8uemv/Lnpr/y56a/8uemv/GlI//o1VM/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/5lBOP/KnJf/+/j4///////////////////////////////////////////////////////////8////gP///2r////8//////////////////////////////////////////////////////z5+f/Nop3/m0Q7/5Y8Mv+WPDL/ljwy/5Y8Mv+WPDL/ljwy/5Y8Mv+WPDL/ljwy/5Y8Mv+WPDL/ljsx/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/5lBOP/KnJf/+/j4///////////////////////////////////////////////////////////8////av///1n////6//////////////////////////////////////////////////////v4+P/KnJf/mUE4/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/5lCOP/KnZj/+/j4///////////////////////////////////////////////////////////6////Wf///0b////o//////////////////////////////////////////////////////v4+P/KnJf/mUE4/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/5pDOv/Qp6P//Pr6///////////////////////////////////////////////////////////o////Rv///zT////V//////////////////////////////////////////////////////v4+P/KnJf/mUE4/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/51IP//bvbr//v7+///////////////////////////////////////////////////////////V////NP///xr///+7//////////////////////////////////////////////////////v4+P/KnJf/mUE4/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/6RVTf/n0c////////////////////////////////////////////////////////////////+7////Gv///wz///+U////+v////////////////////////////////////////////////v4+P/KnJf/mUE4/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/7FuZ//z6ej///////////////////////////////////////////////////////////r///+U////DP///wT///9g////7/////////////////////////////////////////////////z4+P/LnZj/mkI5/5Y8Mv+WPDL/ljwy/5Y8Mv+WPDL/ljwy/5Y8Mv+WPDL/ljwy/5Y8Mv+WPDL/ljwy/5Y8Mv+WPDL/ljwy/5Y8Mv+WPDL/mUE3/8mblf/9+/r//////////////////////////////////////////////////////////+////9g////BAAAAAD///8u////z/////////////////////////////////////////////////38/P/iycb/v4iC/7yCfP+8gnz/vIJ8/7yCfP+8gnz/vIJ8/7yCfP+8gnz/vIJ8/7yCfP+8gnz/voR+/8qcl//Lnpr/y56a/8uemv/Lnpr/zqOf//Hl5P///v7//////////////////////////////////////////////////////////8////8uAAAAAAAAAAD///8I////k/////z////////////////////////////////////////////////9/Pz/+vf2//r39v/69/b/+vf2//r39v/69/b/+vf2//j08//07Ov/7+Df/+7f3v/z6+n/+PPy//z6+v/9+/r//fv6//37+v/9+/r//fv7///+/v///////////////////////////////////////////////////////////P///5P///8IAAAAAAAAAAAAAAAA////Nf///93////+/////////////////////////////////////////////////////////////////////////////v7/9u7t/9i3s/++hn//sW1m/7BsZf+7gnv/066q//Ln5v/+/v7////////////////////////////////////////////////////////////////////////////////+////3f///zUAAAAAAAAAAAAAAAAAAAAA////B////3z////3///////////////////////////////////////////////////////////////////////////17Ov/wo6I/55KQf+XPjT/ljsx/5Y7Mf+XPTP/nEY9/7uBe//x5eP////////////////////////////////////////////////////////////////////////////////3////fP///wcAAAAAAAAAAAAAAAAAAAAAAAAAAP///yr////C/////f////////////////////////////////////////////////////////////////37+//UsKz/nUg//5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/5tEO//No57/+/j4//////////////////////////////////////////////////////////////////////3////C////KgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///wb///9g////5v////////////////////////////////////////////////////////////////bv7/+5fHb/lz0z/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/5Y8Mv+ycGj/8ujm/////////////////////////////////////////////////////////////////////+b///9g////BgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///8R////if////f//////////////////////////////////////////////////////////+3e3P+qYlr/ljsx/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/5Y7Mf+oXVT/6tnX////////////////////////////////////////////////////////////////9////4n///8RAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////GP///6T////z/////////////////////////////////////////////////////+vZ1/+oXVT/ljsx/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/5Y7Mf+nWlL/6dbU///////////////////////////////////////////////////////////z////pP///xgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///yL///+d////8/////////////////////////////////////////////////Hm5f+wa2T/ljsx/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/5Y7Mf+uaGD/8OPh//////////////////////////////////////////////////////P///+d////IgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///wH///8i////pP////f///////////////////////////////////////////r19P/CjYf/mD81/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/5g/Nf/BjIb/+fTz////////////////////////////////////////////////9////6T///8i////AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////GP///4n////m/////f////////////////////////////////7+/v/m0M7/qmFZ/5c9M/+WOzH/ljsx/5Y7Mf+WOzH/lz0z/6leV//lz8z//v7+//////////////////////////////////////3////m////if///xgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///xH///9g////wv////f////+///////////////////////////8+vr/4snG/7d4cf+iUUj/mUA3/5c+NP+gTkT/tXVu/+DFw//8+fn////////////////////////////////+////9////8L///9g////EQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///8G////Kv///3z////d/////P///////////////////////////v38//Tr6v/kzcv/2726/9m6t//jysf/8uno//78/P////////////////////////////////z////d////fP///yr///8GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///wf///81////k////8/////v////+v////////////////////////////////////////////////////////////////////r////v////z////5P///81////BwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////CP///y7///9g////lP///7v////V////6P////r////8/////P////z////8////+v///+j////V////u////5T///9g////Lv///wgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///8E////DP///xr///80////Rv///1n///9q////gP///4D///9q////Wf///0b///80////Gv///wz///8EAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==";
235
+
232
236
  // src/components/Admin/Header.tsx
233
237
  import { Fragment, jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
238
+ var DEFAULT_ADMIN_LOGO = "/images/logo/logo.png";
234
239
  function AdminHeader() {
235
240
  const { data: session } = useSession();
236
241
  const isMobile = useIsMobile();
242
+ const configuredLogo = process.env.NEXT_PUBLIC_ADMIN_LOGO_URL || DEFAULT_ADMIN_LOGO;
243
+ const [logoSrc, setLogoSrc] = useState2(configuredLogo);
244
+ const [logoFailed, setLogoFailed] = useState2(false);
245
+ const isDataLogo = useMemo(() => logoSrc.startsWith("data:"), [logoSrc]);
237
246
  const handleLogout = () => {
238
247
  signOut({ callbackUrl: "/admin/signin" });
239
248
  };
240
249
  return /* @__PURE__ */ jsx3("header", { className: "bg-white border-b border-gray-200 px-4 py-2", children: /* @__PURE__ */ jsxs2("div", { className: "flex items-center justify-between", children: [
241
- /* @__PURE__ */ jsx3("div", { className: "flex items-center max-h-9 shrink-0", children: /* @__PURE__ */ jsx3(
250
+ /* @__PURE__ */ jsx3("div", { className: "flex items-center max-h-9 shrink-0", children: !logoFailed ? /* @__PURE__ */ jsx3(
242
251
  Image,
243
252
  {
244
- src: process.env.NEXT_PUBLIC_ADMIN_LOGO_URL || "/images/logo/logo.png",
253
+ src: logoSrc,
245
254
  alt: "Admin",
246
255
  width: 120,
247
256
  height: 34,
248
- className: "max-h-9 w-auto object-contain object-left"
257
+ className: "max-h-9 w-auto object-contain object-left",
258
+ unoptimized: isDataLogo,
259
+ onError: () => {
260
+ if (logoSrc !== DEFAULT_ADMIN_LOGO) {
261
+ setLogoSrc(DEFAULT_ADMIN_LOGO);
262
+ return;
263
+ }
264
+ setLogoFailed(true);
265
+ }
249
266
  }
250
- ) }),
267
+ ) : /* @__PURE__ */ jsxs2("div", { className: "flex items-center gap-2", children: [
268
+ /* @__PURE__ */ jsx3(Image, { src: INFURO_FAVICON_BASE64, alt: "Infuro", width: 18, height: 18, unoptimized: true }),
269
+ /* @__PURE__ */ jsx3("span", { className: "text-sm font-semibold text-gray-800", children: "Infuro" })
270
+ ] }) }),
251
271
  /* @__PURE__ */ jsx3("div", { className: "flex items-center space-x-3", children: /* @__PURE__ */ jsxs2(DropdownMenu, { children: [
252
272
  /* @__PURE__ */ jsx3(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsxs2(
253
273
  Button,
@@ -330,11 +350,8 @@ var defaultValue = {
330
350
  };
331
351
  var AdminConfigContext = createContext(defaultValue);
332
352
 
333
- // src/lib/infuro-favicon.ts
334
- var INFURO_FAVICON_BASE64 = "data:image/x-icon;base64,AAABAAMAEBAAAAEAIABoBAAANgAAACAgAAABACAAKBEAAJ4EAAAwMAAAAQAgAGgmAADGFQAAKAAAABAAAAAgAAAAAQAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///8V////bv///7D////R////0f///7D///9u////FQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///wL///9s0qun7q9qYv/DkYv/6tfV///+/v///////////////+7///9r////AgAAAAAAAAAAAAAAAP///wL///+Q/////sqcl/+WOzH/ljsx/5c9M//AiYP/+/j4/////////////////v///5D///8CAAAAAAAAAAD///9s/////v/////Oo5//lz00/5Y7Mf+WOzH/ljsx/7Z3cP/9+/v////////////////+////bAAAAAD///8V////7v///////////v39//Tq6f/QqKP/m0U8/5Y7Mf+WOzH/z6ah/////////////////////+7///8V////bv///////////////////////////////+XOy/+ZQTf/ljsx/59MQ//69fX/////////////////////bv///7D/////////////////////////////////////wYyG/5Y7Mf+WOzH/4MTC/////////////////////7D////R//////////////////7+//79/f/+/f3//v39/+DGw/+WOzH/ljsx/82inf/////////////////////R////0f///////////////9Svq/+mWVH/pllR/6ZZUf+iUUj/ljsx/5Y7Mf/KnJf/////////////////////0f///7D////////////////KnJf/ljsx/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/062p/////////////////////7D///9u////////////////0amk/6FQSP+hUEj/oVBI/6JRSP+mWVH/plpS/+7g3v////////////////////9u////Ff///+7///////////7+/v/9/Pz/9u7t/8SSjP/Dj4r/9ezr//79/f/////////////////////u////FQAAAAD///9s/////v///////////////8OPif+WOzH/ljsx/7+Jgv/////////////////////+////bAAAAAAAAAAA////Av///5D////+//////////+9hH7/ljsx/5Y7Mf+8g3z////////////////+////kP///wIAAAAAAAAAAAAAAAD///8C////bP///+7/////8OTi/7R0bP+zcmr/8OLh///////////u////bP///wIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///8V////bv///7D////R////0f///7D///9u////FQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKAAAACAAAABAAAAAAQAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///8C////Hf///0n///95////mf///67///+u////mf///3n///9J////Hf///wIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///8I////Tf///7D////p/////v////////////////////////////////////7////p////sP///03///8IAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///8C////Pfjz8r7HlpH7wY2H/86lof/iysf/9e3s///+/v//////////////////////////////////////////+////77///89////AgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////Cf///37////z9Ovq/6BORf+WOzH/ljsx/5Y8Mv+hUEf/v4iC/+rY1v/+/f3///////////////////////////////////////////H///99////CQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///wr///+d/////P/////06+r/oE5F/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/m0Q7/8WTjf/38PD///////////////////////////////////////////z///+d////CgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///8J////nf////3///////////Tr6v+gTkX/ljsx/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/61mX//w4+L///////////////////////////////////////////3///+d////CQAAAAAAAAAAAAAAAAAAAAAAAAAA////Av///37////8////////////////9Ovq/6BORf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/6daUv/v4uD///////////////////////////////////////////z///9+////AgAAAAAAAAAAAAAAAAAAAAD///89////8//////////////////////48fD/rGRc/5pCOf+YPjT/ljsx/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/6xkXf/37+////////////////////////////////////////////P///89AAAAAAAAAAAAAAAA////CP///77////////////////////////////////7+Pf/8eXj/+DGw/++hn//m0U8/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/8GLhf/9/Pz//////////////////////////////////////////77///8IAAAAAAAAAAD///9N////+/////////////////////////////////////////////////7+/v/p1tP/rGRd/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/mkI4/+XPzf//////////////////////////////////////////+////00AAAAA////Av///7D////////////////////////////////////////////////////////////////06+r/r2pi/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/tndw//38+///////////////////////////////////////////sP///wL///8d////6f/////////////////////////////////////////////////////////////////////x5eP/olJJ/5Y7Mf+WOzH/ljsx/5Y7Mf+aQjn/7dza///////////////////////////////////////////p////Hf///0n////+///////////////////////////////////////////////////////////////////////////Ur6v/ljwy/5Y7Mf+WOzH/ljsx/5Y7Mf/Oo5////////////////////////////////////////////7///9J////ef////////////////////////////////////////////////////////////////////////////////fw7/+jVEv/ljsx/5Y7Mf+WOzH/ljsx/7Nxav///////////////////////////////////////////////3n///+Z/////////////////////////////////////////////////////////////////////////////////////7yCfP+WOzH/ljsx/5Y7Mf+WOzH/pllQ//r29f//////////////////////////////////////////mf///67///////////////////////////////////////////79/f/9/Pz//fz8//38/P/9/Pz//fz8//38/P/9/Pz/yZuW/5Y7Mf+WOzH/ljsx/5Y7Mf+gT0b/9evr//////////////////////////////////////////+u////rv/////////////////////////////////////69vb/wo2I/7Z3cf+2d3H/tndx/7Z3cf+2d3H/tndx/7Z3cf+lV0//ljsx/5Y7Mf+WOzH/ljsx/6BORf/06+r//////////////////////////////////////////67///+Z//////////////////////////////////////Tr6v+gTkX/ljsx/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/oE5F//Tr6v//////////////////////////////////////////mf///3n/////////////////////////////////////9Ovq/6BORf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/5Y7Mf+lVk7/+fPz//////////////////////////////////////////95////Sf////7////////////////////////////////06+r/oE5F/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/7FuZ////v7//////////////////////////////////////v///0n///8d////6f////////////////////////////////Tr6v+gTkX/ljsx/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/zKCb///////////////////////////////////////////p////Hf///wL///+w////////////////////////////////+PLx/7d4cf+tZl//rWZf/61mX/+tZl//rWZf/61mX/+tZl//rmdg/7Z3cP+2d3H/tndx/7h7df/w4uH//////////////////////////////////////////7D///8CAAAAAP///03////7/////////////////////////////////Pv6//z6+f/8+vn//Pr5//z6+f/z6un/48zJ/+LKx//y5+b//fz8//38/P/9/Pz//fz8///////////////////////////////////////////7////TQAAAAAAAAAA////CP///77/////////////////////////////////////////////////////4MXC/6VXTv+WPDL/ljwy/6JRSP/aubb///7+/////////////////////////////////////////////////////77///8IAAAAAAAAAAAAAAAA////Pf////P///////////////////////////////////////////Xs6/+jU0r/ljsx/5Y7Mf+WOzH/ljsx/59MQv/w5OL////////////////////////////////////////////////z////PQAAAAAAAAAAAAAAAAAAAAD///8C////fv////z/////////////////////////////////////3sK//5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/9m5tf///////////////////////////////////////////P///37///8CAAAAAAAAAAAAAAAAAAAAAAAAAAD///8J////nf////3////////////////////////////////ZuLX/ljsx/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/17Sw//////////////////////////////////////3///+d////CQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///8K////nf////z//////////////////////////+zc2v+aQzn/ljsx/5Y7Mf+WOzH/ljsx/5pDOf/r2tj////////////////////////////////8////nf///woAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///8J////fv////P//////////////////////v39/8eYkv+YPjT/ljsx/5Y7Mf+YPjT/xpSP//79/f//////////////////////////8////37///8JAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///8C////Pf///77////7/////////////////fv6/+DEwf/Ekoz/wY2H/97Bvv/8+vr/////////////////////+////77///89////AgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////CP///03///+w////6f////7////////////////////////////////////+////6f///7D///9N////CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///wL///8d////Sf///3n///+Z////rv///67///+Z////ef///0n///8d////AgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKAAAADAAAABgAAAAAQAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///8E////DP///xr///80////Rv///1n///9q////gP///4D///9q////Wf///0b///80////Gv///wz///8EAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////CP///y7///9g////lP///7v////V////6P////r////8/////P////z////8////+v///+j////V////u////5T///9g////Lv///wgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///wf///81////k////8/////v////+v////////////////////////////////////////////////////////////////////r////v////z////5P///81////BwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///8G////Kv37+3zt3Nrd27y5/Nm6t//fxMH/59LQ//Dk4v/48vH//fv6//////////////////////////////////////////////////////////////////////z////d////fP///yr///8GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///xH///9g////wvz5+ffNop3+m0U8/5c+NP+cRz7/pFVN/65oYP+8gnv/0qun/+jU0v/59fT//v7+///////////////////////////////////////////////////////////+////9////8L///9f////EQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////GP///4n////m/////fv4+P/KnJf/mUE4/5Y7Mf+WOzH/ljsx/5Y7Mf+XPTT/m0Q6/6ZaUf/BjIX/6NXT//z5+f////////////////////////////////////////////////////////////////3////k////if///xgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///wH///8i////pP////f///////////v4+P/KnJf/mUE4/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/5Y7Mf+XPjT/oVFI/8yhnP/x5OP//vz8////////////////////////////////////////////////////////////////9////6T///8i////AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///yL///+d////8/////////////////v4+P/KnJf/mUE4/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/5tEOv+3eHL/48rH//37+/////////////////////////////////////////////////////////////////P///+d////IgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////GP///6T////z//////////////////////v4+P/KnJf/mUE4/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/5Y7Mf+YPjT/qFxT/9y+uv/9+vr////////////////////////////////////////////////////////////////z////pP///xgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///8R////if////f///////////////////////////v4+P/KnJf/mUE4/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljsy/6NUS//Yt7P//Pn4////////////////////////////////////////////////////////////////9////4n///8RAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///wb///9g////5v////////////////////////////////v4+P/KnZj/mUI4/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/5c8Mv+pXlb/38PA//38/P///////////////////////////////////////////////////////////////+b///9g////BgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///yr////C/////f////////////////////////////////38+//dwLz/qF1V/51JP/+bRDv/mD40/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/5Y7Mf+XPTP/qWBY/+vZ2P///v7///////////////////////////////////////////////////////////3////C////KgAAAAAAAAAAAAAAAAAAAAAAAAAA////B////3z////3///////////////////////////////////////////9+/r/9/Dv/+zc2f/dwLz/x5iT/7BrY/+eS0H/lz0z/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/lzwy/7d6c//06un////////////////////////////////////////////////////////////////3////fP///wcAAAAAAAAAAAAAAAAAAAAA////Nf///93////+//////////////////////////////////////////////////////7+/v/+/v7//fz8//Hm5f/XtLH/s3Fq/5lCOP+WOzH/ljsx/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/51JP//Sq6b//Pn5///////////////////////////////////////////////////////////+////3f///zUAAAAAAAAAAAAAAAD///8I////k/////z////////////////////////////////////////////////////////////////////////////////9+/v/8eTj/8aVkP+dRz7/ljsx/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/5c8Mv+vamL/7uDf/////////////////////////////////////////////////////////////////P///5P///8IAAAAAAAAAAD///8u////z/////////////////////////////////////////////////////////////////////////////////////////////////fx8P/ImZP/nUg//5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/5Y7Mf+ZQTj/0qyo//38/P///////////////////////////////////////////////////////////////8////8uAAAAAP///wT///9g////7//////////////////////////////////////////////////////////////////////////////////////////////////////07Or/xJGL/5hAN/+WOzH/ljsx/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/rGRd//Tq6P///////////////////////////////////////////////////////////////+////9g////BP///wz///+U////+v////////////////////////////////////////////////////////////////////////////////////////////////////////7/8+jm/7Nya/+WPDP/ljsx/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/mkQ7/9m3s////v7///////////////////////////////////////////////////////////r///+U////DP///xr///+7/////////////////////////////////////////////////////////////////////////////////////////////////////////////////v7+/+HHxP+hUEf/ljsx/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljwy/7yBe//69/f///////////////////////////////////////////////////////////////+7////Gv///zT////V//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////bu7f+7gHr/mD40/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/6xkXP/u4N/////////////////////////////////////////////////////////////////V////NP///0b////o//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////38/P/XtK//nEY9/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/6BNRP/iycb////////////////////////////////////////////////////////////////o////Rv///1n////6///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////o1NL/pVhQ/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/5xGPP/Yt7L//v39///////////////////////////////////////////////////////////6////Wf///2r////8///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////06un/sW1m/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/5pDOf/PpKD//Pr5///////////////////////////////////////////////////////////8////av///4D////8/////////////////////////////////////////////////////////////v7//fv7//37+v/9+/r//fv6//37+v/9+/r//fv6//37+v/9+/r//fv6//37+v/06un/snBp/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/5lBOP/KnJj/+/j4///////////////////////////////////////////////////////////8////gP///4D////8//////////////////////////////////////////////////////79/f/s3Nr/z6ej/8uemv/Lnpr/y56a/8uemv/Lnpr/y56a/8uemv/Lnpr/y56a/8uemv/GlI//o1VM/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/5lBOP/KnJf/+/j4///////////////////////////////////////////////////////////8////gP///2r////8//////////////////////////////////////////////////////z5+f/Nop3/m0Q7/5Y8Mv+WPDL/ljwy/5Y8Mv+WPDL/ljwy/5Y8Mv+WPDL/ljwy/5Y8Mv+WPDL/ljsx/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/5lBOP/KnJf/+/j4///////////////////////////////////////////////////////////8////av///1n////6//////////////////////////////////////////////////////v4+P/KnJf/mUE4/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/5lCOP/KnZj/+/j4///////////////////////////////////////////////////////////6////Wf///0b////o//////////////////////////////////////////////////////v4+P/KnJf/mUE4/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/5pDOv/Qp6P//Pr6///////////////////////////////////////////////////////////o////Rv///zT////V//////////////////////////////////////////////////////v4+P/KnJf/mUE4/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/51IP//bvbr//v7+///////////////////////////////////////////////////////////V////NP///xr///+7//////////////////////////////////////////////////////v4+P/KnJf/mUE4/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/6RVTf/n0c////////////////////////////////////////////////////////////////+7////Gv///wz///+U////+v////////////////////////////////////////////////v4+P/KnJf/mUE4/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/7FuZ//z6ej///////////////////////////////////////////////////////////r///+U////DP///wT///9g////7/////////////////////////////////////////////////z4+P/LnZj/mkI5/5Y8Mv+WPDL/ljwy/5Y8Mv+WPDL/ljwy/5Y8Mv+WPDL/ljwy/5Y8Mv+WPDL/ljwy/5Y8Mv+WPDL/ljwy/5Y8Mv+WPDL/mUE3/8mblf/9+/r//////////////////////////////////////////////////////////+////9g////BAAAAAD///8u////z/////////////////////////////////////////////////38/P/iycb/v4iC/7yCfP+8gnz/vIJ8/7yCfP+8gnz/vIJ8/7yCfP+8gnz/vIJ8/7yCfP+8gnz/voR+/8qcl//Lnpr/y56a/8uemv/Lnpr/zqOf//Hl5P///v7//////////////////////////////////////////////////////////8////8uAAAAAAAAAAD///8I////k/////z////////////////////////////////////////////////9/Pz/+vf2//r39v/69/b/+vf2//r39v/69/b/+vf2//j08//07Ov/7+Df/+7f3v/z6+n/+PPy//z6+v/9+/r//fv6//37+v/9+/r//fv7///+/v///////////////////////////////////////////////////////////P///5P///8IAAAAAAAAAAAAAAAA////Nf///93////+/////////////////////////////////////////////////////////////////////////////v7/9u7t/9i3s/++hn//sW1m/7BsZf+7gnv/066q//Ln5v/+/v7////////////////////////////////////////////////////////////////////////////////+////3f///zUAAAAAAAAAAAAAAAAAAAAA////B////3z////3///////////////////////////////////////////////////////////////////////////17Ov/wo6I/55KQf+XPjT/ljsx/5Y7Mf+XPTP/nEY9/7uBe//x5eP////////////////////////////////////////////////////////////////////////////////3////fP///wcAAAAAAAAAAAAAAAAAAAAAAAAAAP///yr////C/////f////////////////////////////////////////////////////////////////37+//UsKz/nUg//5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/5tEO//No57/+/j4//////////////////////////////////////////////////////////////////////3////C////KgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///wb///9g////5v////////////////////////////////////////////////////////////////bv7/+5fHb/lz0z/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/5Y8Mv+ycGj/8ujm/////////////////////////////////////////////////////////////////////+b///9g////BgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///8R////if////f//////////////////////////////////////////////////////////+3e3P+qYlr/ljsx/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/5Y7Mf+oXVT/6tnX////////////////////////////////////////////////////////////////9////4n///8RAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////GP///6T////z/////////////////////////////////////////////////////+vZ1/+oXVT/ljsx/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/5Y7Mf+nWlL/6dbU///////////////////////////////////////////////////////////z////pP///xgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///yL///+d////8/////////////////////////////////////////////////Hm5f+wa2T/ljsx/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/5Y7Mf+uaGD/8OPh//////////////////////////////////////////////////////P///+d////IgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///wH///8i////pP////f///////////////////////////////////////////r19P/CjYf/mD81/5Y7Mf+WOzH/ljsx/5Y7Mf+WOzH/ljsx/5g/Nf/BjIb/+fTz////////////////////////////////////////////////9////6T///8i////AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////GP///4n////m/////f////////////////////////////////7+/v/m0M7/qmFZ/5c9M/+WOzH/ljsx/5Y7Mf+WOzH/lz0z/6leV//lz8z//v7+//////////////////////////////////////3////m////if///xgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///xH///9g////wv////f////+///////////////////////////8+vr/4snG/7d4cf+iUUj/mUA3/5c+NP+gTkT/tXVu/+DFw//8+fn////////////////////////////////+////9////8L///9g////EQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///8G////Kv///3z////d/////P///////////////////////////v38//Tr6v/kzcv/2726/9m6t//jysf/8uno//78/P////////////////////////////////z////d////fP///yr///8GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///wf///81////k////8/////v////+v////////////////////////////////////////////////////////////////////r////v////z////5P///81////BwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////CP///y7///9g////lP///7v////V////6P////r////8/////P////z////8////+v///+j////V////u////5T///9g////Lv///wgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///8E////DP///xr///80////Rv///1n///9q////gP///4D///9q////Wf///0b///80////Gv///wz///8EAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==";
335
-
336
353
  // src/lib/cms-version.ts
337
- var CMS_VERSION = true ? "1.0.14" : "0.0.0";
354
+ var CMS_VERSION = true ? "1.0.16" : "0.0.0";
338
355
 
339
356
  // src/components/Admin/Sidebar.tsx
340
357
  import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
@@ -743,8 +760,8 @@ function AdminLayoutInner({ children }) {
743
760
  const { data: session, status } = useSession2();
744
761
  const router = useRouter();
745
762
  const pathname = usePathname3();
746
- const [loadingTimeout, setLoadingTimeout] = useState2(false);
747
- const [moreSheetOpen, setMoreSheetOpen] = useState2(false);
763
+ const [loadingTimeout, setLoadingTimeout] = useState3(false);
764
+ const [moreSheetOpen, setMoreSheetOpen] = useState3(false);
748
765
  const isMobile = useIsMobile();
749
766
  useAdminViewSettings();
750
767
  const isPublicPath = PUBLIC_ADMIN_PATHS.includes(pathname);
@@ -806,7 +823,7 @@ function AdminLayoutInner({ children }) {
806
823
  ] });
807
824
  }
808
825
  function useResolvedTheme(theme, themeRegistry) {
809
- const [activeThemeId, setActiveThemeId] = useState2(null);
826
+ const [activeThemeId, setActiveThemeId] = useState3(null);
810
827
  useEffect2(() => {
811
828
  if (!themeRegistry || themeRegistry.length === 0) return;
812
829
  fetch("/api/settings/theme").then((r) => r.ok ? r.json() : {}).then((data) => {
@@ -821,7 +838,7 @@ function useResolvedTheme(theme, themeRegistry) {
821
838
  return found?.config ?? theme ?? themeRegistry[0]?.config;
822
839
  }
823
840
  function useStoreEnabled() {
824
- const [storeEnabled, setStoreEnabled] = useState2(false);
841
+ const [storeEnabled, setStoreEnabled] = useState3(false);
825
842
  useEffect2(() => {
826
843
  fetch("/api/settings/store").then((r) => r.ok ? r.json() : {}).then((data) => {
827
844
  setStoreEnabled(data?.enabled === "true");
@@ -863,10 +880,10 @@ function AdminShell({ children }) {
863
880
  }
864
881
 
865
882
  // src/components/Admin/CRUD.tsx
866
- import { useEffect as useEffect6, useState as useState7 } from "react";
883
+ import { useEffect as useEffect6, useRef as useRef3, useState as useState8 } from "react";
867
884
 
868
885
  // src/components/Admin/CreateEditForm.tsx
869
- import { useState as useState5, useEffect as useEffect4 } from "react";
886
+ import { useState as useState6, useEffect as useEffect4 } from "react";
870
887
  import { X as X2 } from "lucide-react";
871
888
 
872
889
  // src/components/ui/input.tsx
@@ -1064,7 +1081,7 @@ var Label3 = React10.forwardRef(({ className, ...props }, ref) => /* @__PURE__ *
1064
1081
  Label3.displayName = LabelPrimitive.Root.displayName;
1065
1082
 
1066
1083
  // src/components/ui/file-upload.tsx
1067
- import { useState as useState3 } from "react";
1084
+ import { useState as useState4 } from "react";
1068
1085
 
1069
1086
  // src/components/ui/progress.tsx
1070
1087
  import * as React11 from "react";
@@ -1093,10 +1110,10 @@ Progress.displayName = ProgressPrimitive.Root.displayName;
1093
1110
  // src/components/ui/file-upload.tsx
1094
1111
  import { jsx as jsx15, jsxs as jsxs9 } from "react/jsx-runtime";
1095
1112
  function FileUpload({ onUploadSuccess }) {
1096
- const [selectedFile, setSelectedFile] = useState3(null);
1097
- const [uploading, setUploading] = useState3(false);
1098
- const [progress, setProgress] = useState3(0);
1099
- const [fileUrl, setFileUrl] = useState3("");
1113
+ const [selectedFile, setSelectedFile] = useState4(null);
1114
+ const [uploading, setUploading] = useState4(false);
1115
+ const [progress, setProgress] = useState4(0);
1116
+ const [fileUrl, setFileUrl] = useState4("");
1100
1117
  const handleFileChange = (event) => {
1101
1118
  setSelectedFile(event.target.files[0]);
1102
1119
  };
@@ -1137,7 +1154,7 @@ function FileUpload({ onUploadSuccess }) {
1137
1154
  }
1138
1155
 
1139
1156
  // src/components/Admin/RelationAutocomplete.tsx
1140
- import { useState as useState4, useEffect as useEffect3, useRef, useCallback } from "react";
1157
+ import { useState as useState5, useEffect as useEffect3, useRef, useCallback } from "react";
1141
1158
  import { ChevronDown as ChevronDown3 } from "lucide-react";
1142
1159
  import { jsx as jsx16, jsxs as jsxs10 } from "react/jsx-runtime";
1143
1160
  var DEBOUNCE_MS = 300;
@@ -1151,16 +1168,16 @@ function RelationAutocomplete({
1151
1168
  placeholder = "Select\u2026",
1152
1169
  disabled = false
1153
1170
  }) {
1154
- const [open, setOpen] = useState4(false);
1155
- const [search, setSearch] = useState4("");
1156
- const [searchInput, setSearchInput] = useState4("");
1157
- const [items, setItems] = useState4([]);
1158
- const [total, setTotal] = useState4(0);
1159
- const [page, setPage] = useState4(1);
1160
- const [loading, setLoading] = useState4(false);
1161
- const [loadingMore, setLoadingMore] = useState4(false);
1162
- const [selectedLabel, setSelectedLabel] = useState4(null);
1163
- const [initialLabelLoaded, setInitialLabelLoaded] = useState4(false);
1171
+ const [open, setOpen] = useState5(false);
1172
+ const [search, setSearch] = useState5("");
1173
+ const [searchInput, setSearchInput] = useState5("");
1174
+ const [items, setItems] = useState5([]);
1175
+ const [total, setTotal] = useState5(0);
1176
+ const [page, setPage] = useState5(1);
1177
+ const [loading, setLoading] = useState5(false);
1178
+ const [loadingMore, setLoadingMore] = useState5(false);
1179
+ const [selectedLabel, setSelectedLabel] = useState5(null);
1180
+ const [initialLabelLoaded, setInitialLabelLoaded] = useState5(false);
1164
1181
  const containerRef = useRef(null);
1165
1182
  const listRef = useRef(null);
1166
1183
  const debounceRef = useRef(null);
@@ -1207,6 +1224,12 @@ function RelationAutocomplete({
1207
1224
  if (debounceRef.current) clearTimeout(debounceRef.current);
1208
1225
  };
1209
1226
  }, [searchInput, open]);
1227
+ useEffect3(() => {
1228
+ if (open) return;
1229
+ setSearchInput("");
1230
+ setSearch("");
1231
+ setPage(1);
1232
+ }, [open]);
1210
1233
  const loadInitialLabel = useCallback(() => {
1211
1234
  if (initialLabelLoaded || value == null || value === "") return;
1212
1235
  setInitialLabelLoaded(true);
@@ -1334,8 +1357,8 @@ import { toast } from "sonner";
1334
1357
  import { jsx as jsx17, jsxs as jsxs11 } from "react/jsx-runtime";
1335
1358
  function CreateEditForm({ isOpen, onClose, apiEndpoint, columns, existingData }) {
1336
1359
  const isMobile = useIsMobile();
1337
- const [formData, setFormData] = useState5({});
1338
- const [errors, setErrors] = useState5({});
1360
+ const [formData, setFormData] = useState6({});
1361
+ const [errors, setErrors] = useState6({});
1339
1362
  useEffect4(() => {
1340
1363
  if (existingData) {
1341
1364
  setFormData(existingData);
@@ -1623,7 +1646,7 @@ var DialogContent = React14.forwardRef(({ className, children, ...props }, ref)
1623
1646
  {
1624
1647
  ref,
1625
1648
  className: cn(
1626
- "fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg",
1649
+ "fixed left-[50%] top-[50%] z-50 grid w-[calc(100vw-1rem)] max-w-lg max-h-[calc(100vh-1rem)] translate-x-[-50%] translate-y-[-50%] gap-4 overflow-y-auto rounded-lg border bg-background p-4 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:max-h-[calc(100vh-2rem)] sm:p-6",
1627
1650
  className
1628
1651
  ),
1629
1652
  ...props,
@@ -1659,7 +1682,7 @@ var DialogFooter = ({
1659
1682
  "div",
1660
1683
  {
1661
1684
  className: cn(
1662
- "flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2",
1685
+ "flex flex-col-reverse gap-2 sm:flex-row sm:justify-end sm:space-x-2 sm:gap-0 [&>button]:w-full sm:[&>button]:w-auto",
1663
1686
  className
1664
1687
  ),
1665
1688
  ...props
@@ -1689,11 +1712,12 @@ var DialogDescription = React14.forwardRef(({ className, ...props }, ref) => /*
1689
1712
  DialogDescription.displayName = DialogPrimitive.Description.displayName;
1690
1713
 
1691
1714
  // src/components/Admin/CRUD.tsx
1692
- import { Edit, Trash2, Eye, Plus, Search, Check as Check3, X as X5, RefreshCw, Upload as Upload2, Download as Download2, MoreVertical, Filter } from "lucide-react";
1715
+ import { Edit, Trash2, Plus, Search, Check as Check3, X as X5, RefreshCw, Upload as Upload2, Download as Download2, MoreVertical, Filter } from "lucide-react";
1693
1716
  import Link4 from "next/link";
1717
+ import { useRouter as useRouter2 } from "next/navigation";
1694
1718
 
1695
1719
  // src/components/Admin/BulkUploadDialog.tsx
1696
- import { useState as useState6, useEffect as useEffect5, useRef as useRef2 } from "react";
1720
+ import { useState as useState7, useEffect as useEffect5, useRef as useRef2 } from "react";
1697
1721
  import { Download, Upload, AlertCircle, CheckCircle2, X as X4 } from "lucide-react";
1698
1722
  import Papa from "papaparse";
1699
1723
  import { jsx as jsx21, jsxs as jsxs14 } from "react/jsx-runtime";
@@ -1708,16 +1732,16 @@ var AUTO_GENERATED_COLS = /* @__PURE__ */ new Set([
1708
1732
  "deleted"
1709
1733
  ]);
1710
1734
  function BulkUploadDialog({ apiEndpoint, onClose }) {
1711
- const [columns, setColumns] = useState6([]);
1712
- const [uniqueColumns, setUniqueColumns] = useState6([]);
1713
- const [loading, setLoading] = useState6(true);
1714
- const [importing, setImporting] = useState6(false);
1715
- const [error, setError] = useState6(null);
1716
- const [success, setSuccess] = useState6(null);
1717
- const [parsedData, setParsedData] = useState6([]);
1718
- const [parseErrors, setParseErrors] = useState6([]);
1719
- const [upsertKey, setUpsertKey] = useState6("id");
1720
- const [fileName, setFileName] = useState6("");
1735
+ const [columns, setColumns] = useState7([]);
1736
+ const [uniqueColumns, setUniqueColumns] = useState7([]);
1737
+ const [loading, setLoading] = useState7(true);
1738
+ const [importing, setImporting] = useState7(false);
1739
+ const [error, setError] = useState7(null);
1740
+ const [success, setSuccess] = useState7(null);
1741
+ const [parsedData, setParsedData] = useState7([]);
1742
+ const [parseErrors, setParseErrors] = useState7([]);
1743
+ const [upsertKey, setUpsertKey] = useState7("id");
1744
+ const [fileName, setFileName] = useState7("");
1721
1745
  const fileInputRef = useRef2(null);
1722
1746
  useEffect5(() => {
1723
1747
  fetchMetadata();
@@ -1961,6 +1985,7 @@ function BulkUploadDialog({ apiEndpoint, onClose }) {
1961
1985
  }
1962
1986
 
1963
1987
  // src/components/Admin/CRUD.tsx
1988
+ import { toast as toast2 } from "sonner";
1964
1989
  import { Fragment as Fragment3, jsx as jsx22, jsxs as jsxs15 } from "react/jsx-runtime";
1965
1990
  function getNestedValue(obj, path) {
1966
1991
  return path.split(".").reduce((current, key) => {
@@ -1985,27 +2010,40 @@ function AdminCRUD({
1985
2010
  extraListParams,
1986
2011
  manageUserGroups
1987
2012
  }) {
1988
- const [data, setData] = useState7([]);
1989
- const [loading, setLoading] = useState7(true);
1990
- const [error, setError] = useState7(null);
1991
- const [page, setPage] = useState7(1);
1992
- const [totalPages, setTotalPages] = useState7(1);
1993
- const [sortField, setSortField] = useState7(defaultSortField);
1994
- const [sortOrder, setSortOrder] = useState7(defaultSortOrder);
1995
- const [searchQuery, setSearchQuery] = useState7("");
1996
- const [filterValues, setFilterValues] = useState7({});
1997
- const [filterApplyKey, setFilterApplyKey] = useState7(0);
1998
- const [isFormOpen, setIsFormOpen] = useState7(false);
1999
- const [editingItem, setEditingItem] = useState7(null);
2000
- const [deleteDialogOpen, setDeleteDialogOpen] = useState7(false);
2001
- const [itemToDelete, setItemToDelete] = useState7(null);
2002
- const [deleteLoading, setDeleteLoading] = useState7(false);
2003
- const [refreshKey, setRefreshKey] = useState7(0);
2004
- const [bulkDialogOpen, setBulkDialogOpen] = useState7(false);
2005
- const [showFilters, setShowFilters] = useState7(false);
2006
- const [roleOptions, setRoleOptions] = useState7([]);
2013
+ const router = useRouter2();
2014
+ const [data, setData] = useState8([]);
2015
+ const [loading, setLoading] = useState8(true);
2016
+ const [error, setError] = useState8(null);
2017
+ const [page, setPage] = useState8(1);
2018
+ const [totalPages, setTotalPages] = useState8(1);
2019
+ const [sortField, setSortField] = useState8(defaultSortField);
2020
+ const [sortOrder, setSortOrder] = useState8(defaultSortOrder);
2021
+ const [searchQuery, setSearchQuery] = useState8("");
2022
+ const [searchInput, setSearchInput] = useState8("");
2023
+ const [filterValues, setFilterValues] = useState8({});
2024
+ const [filterApplyKey, setFilterApplyKey] = useState8(0);
2025
+ const [isFormOpen, setIsFormOpen] = useState8(false);
2026
+ const [editingItem, setEditingItem] = useState8(null);
2027
+ const [deleteDialogOpen, setDeleteDialogOpen] = useState8(false);
2028
+ const [itemToDelete, setItemToDelete] = useState8(null);
2029
+ const [deleteLoading, setDeleteLoading] = useState8(false);
2030
+ const [refreshKey, setRefreshKey] = useState8(0);
2031
+ const [bulkDialogOpen, setBulkDialogOpen] = useState8(false);
2032
+ const [showFilters, setShowFilters] = useState8(false);
2033
+ const [isRefetching, setIsRefetching] = useState8(false);
2034
+ const [roleOptions, setRoleOptions] = useState8([]);
2035
+ const hasLoadedRef = useRef3(false);
2007
2036
  const isMobile = useIsMobile();
2008
2037
  const showGroupColumn = !!manageUserGroups && roleOptions.length > 0;
2038
+ useEffect6(() => {
2039
+ const timeoutId = setTimeout(() => {
2040
+ if (searchInput !== searchQuery) {
2041
+ setPage(1);
2042
+ setSearchQuery(searchInput);
2043
+ }
2044
+ }, 300);
2045
+ return () => clearTimeout(timeoutId);
2046
+ }, [searchInput, searchQuery]);
2009
2047
  useEffect6(() => {
2010
2048
  if (!manageUserGroups) return;
2011
2049
  fetch("/api/admin/roles").then((r) => r.ok ? r.json() : null).then((data2) => {
@@ -2016,7 +2054,11 @@ function AdminCRUD({
2016
2054
  useEffect6(() => {
2017
2055
  async function loadData() {
2018
2056
  try {
2019
- setLoading(true);
2057
+ if (!hasLoadedRef.current) {
2058
+ setLoading(true);
2059
+ } else {
2060
+ setIsRefetching(true);
2061
+ }
2020
2062
  setError(null);
2021
2063
  const params = new URLSearchParams({
2022
2064
  page: page.toString(),
@@ -2056,6 +2098,8 @@ function AdminCRUD({
2056
2098
  setTotalPages(1);
2057
2099
  } finally {
2058
2100
  setLoading(false);
2101
+ setIsRefetching(false);
2102
+ hasLoadedRef.current = true;
2059
2103
  }
2060
2104
  }
2061
2105
  loadData();
@@ -2066,30 +2110,67 @@ function AdminCRUD({
2066
2110
  };
2067
2111
  const handleSearch = () => {
2068
2112
  setPage(1);
2113
+ setSearchQuery(searchInput);
2069
2114
  };
2070
2115
  const handleApplyFilters = () => {
2071
2116
  setPage(1);
2072
2117
  setFilterApplyKey((k) => k + 1);
2073
2118
  };
2119
+ const closeDeleteDialog = () => {
2120
+ console.debug("[CRUD][delete] closeDeleteDialog", {
2121
+ open: deleteDialogOpen,
2122
+ itemId: itemToDelete?.id,
2123
+ loading: deleteLoading
2124
+ });
2125
+ setDeleteDialogOpen(false);
2126
+ setItemToDelete(null);
2127
+ setDeleteLoading(false);
2128
+ };
2074
2129
  const handleDeleteClick = (item) => {
2130
+ console.debug("[CRUD][delete] handleDeleteClick", {
2131
+ itemId: item?.id,
2132
+ resource: resourceName
2133
+ });
2134
+ const active = typeof document !== "undefined" ? document.activeElement : null;
2135
+ if (active instanceof HTMLElement) {
2136
+ active.blur();
2137
+ }
2138
+ setDeleteLoading(false);
2075
2139
  setItemToDelete(item);
2076
- setDeleteDialogOpen(true);
2140
+ window.setTimeout(() => {
2141
+ setDeleteDialogOpen(true);
2142
+ }, 0);
2077
2143
  };
2078
2144
  const handleDelete = async () => {
2079
- if (!itemToDelete) return;
2145
+ if (!itemToDelete) {
2146
+ console.debug("[CRUD][delete] handleDelete blocked: no itemToDelete");
2147
+ return;
2148
+ }
2149
+ console.debug("[CRUD][delete] handleDelete start", {
2150
+ itemId: itemToDelete.id,
2151
+ resource: resourceName
2152
+ });
2080
2153
  setDeleteLoading(true);
2081
2154
  try {
2082
2155
  const res = await fetch(`${apiEndpoint}/${itemToDelete.id}`, { method: "DELETE" });
2156
+ console.debug("[CRUD][delete] handleDelete response", {
2157
+ itemId: itemToDelete.id,
2158
+ ok: res.ok,
2159
+ status: res.status
2160
+ });
2083
2161
  if (res.ok) {
2162
+ setData((prev) => prev.filter((row) => String(row.id) !== String(itemToDelete.id)));
2084
2163
  setRefreshKey((k) => k + 1);
2085
- setDeleteDialogOpen(false);
2086
- setItemToDelete(null);
2164
+ closeDeleteDialog();
2087
2165
  } else {
2088
2166
  console.error("Failed to delete item");
2089
2167
  }
2090
2168
  } catch (err) {
2091
2169
  console.error("Error deleting item:", err);
2092
2170
  } finally {
2171
+ console.debug("[CRUD][delete] handleDelete finally", {
2172
+ itemId: itemToDelete?.id
2173
+ });
2093
2174
  setDeleteLoading(false);
2094
2175
  }
2095
2176
  };
@@ -2124,18 +2205,33 @@ function AdminCRUD({
2124
2205
  }
2125
2206
  const result = await res.json();
2126
2207
  if (result.inviteLink) {
2127
- alert(`New invite link generated: ${result.inviteLink}
2128
-
2129
- Note: ${result.note}`);
2208
+ const note = result.note ? ` ${result.note}` : "";
2209
+ toast2.success(`New invite link generated.${note}`);
2130
2210
  }
2131
2211
  } catch (error2) {
2132
2212
  console.error("Error regenerating invite:", error2);
2133
- alert(error2 instanceof Error ? error2.message : "Failed to regenerate invite");
2213
+ toast2.error(error2 instanceof Error ? error2.message : "Failed to regenerate invite");
2134
2214
  }
2135
2215
  };
2136
2216
  const addEditPage = addEditPageUrl && addEditPageUrl.length > 0;
2137
2217
  const hasCustomView = customViewPageUrl && customViewPageUrl.length > 0;
2138
2218
  const resourceName = apiEndpoint.replace("/api/", "");
2219
+ const hasDetailViewPage = (/* @__PURE__ */ new Set(["contacts", "form-submissions", "orders", "payments"])).has(resourceName);
2220
+ const getRowDestination = (item) => {
2221
+ if (item.id == null) return "modal";
2222
+ if (addEditPage) return `${addEditPageUrl}/${item.id}`;
2223
+ if (hasCustomView) return `${customViewPageUrl}/${item.id}`;
2224
+ if (hasDetailViewPage) return `/admin/${resourceName}/${item.id}/view`;
2225
+ return "modal";
2226
+ };
2227
+ const handleRowClick = (item) => {
2228
+ const destination = getRowDestination(item);
2229
+ if (destination === "modal") {
2230
+ handleEdit(item);
2231
+ return;
2232
+ }
2233
+ router.push(destination);
2234
+ };
2139
2235
  const handleExport = async () => {
2140
2236
  try {
2141
2237
  const res = await fetch(`${apiEndpoint}/export?format=csv`);
@@ -2149,7 +2245,7 @@ Note: ${result.note}`);
2149
2245
  URL.revokeObjectURL(url);
2150
2246
  } catch (err) {
2151
2247
  console.error("Export error:", err);
2152
- alert("Failed to export data");
2248
+ toast2.error("Failed to export data");
2153
2249
  }
2154
2250
  };
2155
2251
  if (loading) {
@@ -2289,8 +2385,8 @@ Note: ${result.note}`);
2289
2385
  {
2290
2386
  type: "text",
2291
2387
  placeholder: "Search...",
2292
- value: searchQuery,
2293
- onChange: (e) => setSearchQuery(e.target.value),
2388
+ value: searchInput,
2389
+ onChange: (e) => setSearchInput(e.target.value),
2294
2390
  onKeyDown: (e) => e.key === "Enter" && handleSearch(),
2295
2391
  className: "border-0 focus-visible:ring-0 focus-visible:ring-offset-0 rounded-l-md rounded-r-none flex-1 min-w-0"
2296
2392
  }
@@ -2384,6 +2480,10 @@ Note: ${result.note}`);
2384
2480
  }),
2385
2481
  /* @__PURE__ */ jsx22(Button, { variant: "outline", size: "sm", className: "h-8", onClick: handleApplyFilters, children: "Apply filters" })
2386
2482
  ] }),
2483
+ isRefetching && /* @__PURE__ */ jsxs15("div", { className: "mb-3 flex items-center text-xs text-gray-500", children: [
2484
+ /* @__PURE__ */ jsx22("div", { className: "animate-spin rounded-full h-3.5 w-3.5 border-2 border-gray-300 border-t-gray-600" }),
2485
+ /* @__PURE__ */ jsx22("span", { className: "ml-2", children: "Refreshing list..." })
2486
+ ] }),
2387
2487
  isMobile ? /* @__PURE__ */ jsx22("div", { className: "flex flex-col gap-2 min-w-0", children: data && data.length > 0 ? data.map((item, index) => {
2388
2488
  const displayCols = columns?.slice(0, 4) ?? [];
2389
2489
  const primary = displayCols[0];
@@ -2391,27 +2491,17 @@ Note: ${result.note}`);
2391
2491
  return /* @__PURE__ */ jsxs15(
2392
2492
  "div",
2393
2493
  {
2394
- className: "min-w-0 rounded-md border border-gray-200 bg-gray-50/50 p-2.5 flex flex-col gap-1",
2494
+ className: "min-w-0 rounded-md border border-gray-200 bg-gray-50/50 p-2.5 flex flex-col gap-1 cursor-pointer",
2495
+ onClick: () => handleRowClick(item),
2395
2496
  children: [
2396
2497
  /* @__PURE__ */ jsxs15("div", { className: "flex items-center justify-between gap-2", children: [
2397
2498
  /* @__PURE__ */ jsx22("div", { className: "min-w-0 break-words flex-1 leading-tight", children: /* @__PURE__ */ jsx22("span", { className: "font-medium", children: primaryVal != null ? String(primaryVal) : "\u2014" }) }),
2398
- /* @__PURE__ */ jsxs15(DropdownMenu, { children: [
2499
+ /* @__PURE__ */ jsx22("div", { onClick: (e) => e.stopPropagation(), children: /* @__PURE__ */ jsxs15(DropdownMenu, { children: [
2399
2500
  /* @__PURE__ */ jsx22(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsxs15(Button, { variant: "ghost", size: "icon", className: "h-8 w-8 shrink-0", children: [
2400
2501
  /* @__PURE__ */ jsx22(MoreVertical, { className: "h-4 w-4" }),
2401
2502
  /* @__PURE__ */ jsx22("span", { className: "sr-only", children: "Actions" })
2402
2503
  ] }) }),
2403
2504
  /* @__PURE__ */ jsxs15(DropdownMenuContent, { align: "end", children: [
2404
- /* @__PURE__ */ jsx22(DropdownMenuItem, { asChild: true, children: /* @__PURE__ */ jsxs15(
2405
- Link4,
2406
- {
2407
- href: hasCustomView ? `${customViewPageUrl}/${item.id}` : `/admin/${resourceName}/${item.id}/view`,
2408
- className: "flex items-center gap-2",
2409
- children: [
2410
- /* @__PURE__ */ jsx22(Eye, { className: "h-4 w-4" }),
2411
- "View"
2412
- ]
2413
- }
2414
- ) }),
2415
2505
  !addEditPage && /* @__PURE__ */ jsxs15(DropdownMenuItem, { onClick: () => handleEdit(item), children: [
2416
2506
  /* @__PURE__ */ jsx22(Edit, { className: "h-4 w-4 mr-2" }),
2417
2507
  "Edit"
@@ -2436,7 +2526,7 @@ Note: ${result.note}`);
2436
2526
  }
2437
2527
  )
2438
2528
  ] })
2439
- ] })
2529
+ ] }, `mobile-actions-${String(item.id ?? index)}-${refreshKey}`) })
2440
2530
  ] }),
2441
2531
  displayCols.slice(1).map((col) => /* @__PURE__ */ jsxs15("div", { className: "text-sm text-gray-600 flex gap-1 min-w-0 leading-tight", children: [
2442
2532
  /* @__PURE__ */ jsxs15("span", { className: "shrink-0", children: [
@@ -2445,7 +2535,7 @@ Note: ${result.note}`);
2445
2535
  ] }),
2446
2536
  /* @__PURE__ */ jsx22("span", { className: "min-w-0 break-words", children: formatCellValue(getNestedValue(item, col.field || col.key), col) })
2447
2537
  ] }, col.field || col.key)),
2448
- showGroupColumn && /* @__PURE__ */ jsxs15("div", { className: "text-sm text-gray-600 flex gap-1 items-center min-w-0", children: [
2538
+ showGroupColumn && /* @__PURE__ */ jsxs15("div", { className: "text-sm text-gray-600 flex gap-1 items-center min-w-0", onClick: (e) => e.stopPropagation(), children: [
2449
2539
  /* @__PURE__ */ jsx22("span", { className: "shrink-0", children: "Group:" }),
2450
2540
  /* @__PURE__ */ jsxs15(
2451
2541
  "select",
@@ -2485,70 +2575,94 @@ Note: ${result.note}`);
2485
2575
  showGroupColumn && /* @__PURE__ */ jsx22(TableHead, { className: "min-w-[140px]", children: "Group" }),
2486
2576
  /* @__PURE__ */ jsx22(TableHead, { className: "w-12 text-center", children: "Actions" })
2487
2577
  ] }) }),
2488
- /* @__PURE__ */ jsx22(TableBody, { children: data && data.length > 0 ? data.map((item, index) => /* @__PURE__ */ jsxs15(TableRow, { children: [
2489
- columns && columns.map((col, colIndex) => {
2490
- const fieldKey = col.field || col.key;
2491
- const value = getNestedValue(item, fieldKey);
2492
- return /* @__PURE__ */ jsx22(TableCell, { children: formatCellValue(value, col) }, `${item.id}-${colIndex}-${fieldKey}`);
2493
- }),
2494
- showGroupColumn && /* @__PURE__ */ jsx22(TableCell, { children: /* @__PURE__ */ jsxs15(
2495
- "select",
2496
- {
2497
- className: "max-w-[180px] rounded border border-gray-300 px-2 py-1 text-sm dark:border-gray-600 dark:bg-gray-800",
2498
- value: item.groupId != null && roleOptions.some((g) => g.id === item.groupId) ? String(item.groupId) : "",
2499
- onChange: (e) => {
2500
- const v = e.target.value;
2501
- if (v) handleUserGroupChange(Number(item.id), Number(v));
2502
- },
2503
- children: [
2504
- /* @__PURE__ */ jsx22("option", { value: "", children: "\u2014" }),
2505
- roleOptions.map((g) => /* @__PURE__ */ jsx22("option", { value: g.id, children: g.name }, g.id))
2506
- ]
2507
- }
2508
- ) }),
2509
- /* @__PURE__ */ jsx22(TableCell, { className: "text-center", children: /* @__PURE__ */ jsxs15(DropdownMenu, { children: [
2510
- /* @__PURE__ */ jsx22(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsxs15(Button, { variant: "ghost", size: "icon", className: "h-8 w-8", children: [
2511
- /* @__PURE__ */ jsx22(MoreVertical, { className: "h-4 w-4" }),
2512
- /* @__PURE__ */ jsx22("span", { className: "sr-only", children: "Actions" })
2513
- ] }) }),
2514
- /* @__PURE__ */ jsxs15(DropdownMenuContent, { align: "end", children: [
2515
- /* @__PURE__ */ jsx22(DropdownMenuItem, { asChild: true, children: /* @__PURE__ */ jsxs15(
2516
- Link4,
2578
+ /* @__PURE__ */ jsx22(TableBody, { children: data && data.length > 0 ? data.map((item, index) => /* @__PURE__ */ jsxs15(
2579
+ TableRow,
2580
+ {
2581
+ className: "cursor-pointer",
2582
+ onClick: () => handleRowClick(item),
2583
+ children: [
2584
+ columns && columns.map((col, colIndex) => {
2585
+ const fieldKey = col.field || col.key;
2586
+ const value = getNestedValue(item, fieldKey);
2587
+ return /* @__PURE__ */ jsx22(TableCell, { children: formatCellValue(value, col) }, `${item.id}-${colIndex}-${fieldKey}`);
2588
+ }),
2589
+ showGroupColumn && /* @__PURE__ */ jsx22(TableCell, { onClick: (e) => e.stopPropagation(), children: /* @__PURE__ */ jsxs15(
2590
+ "select",
2517
2591
  {
2518
- href: hasCustomView ? `${customViewPageUrl}/${item.id}` : `/admin/${resourceName}/${item.id}/view`,
2519
- className: "flex items-center gap-2",
2592
+ className: "max-w-[180px] rounded border border-gray-300 px-2 py-1 text-sm dark:border-gray-600 dark:bg-gray-800",
2593
+ value: item.groupId != null && roleOptions.some((g) => g.id === item.groupId) ? String(item.groupId) : "",
2594
+ onChange: (e) => {
2595
+ const v = e.target.value;
2596
+ if (v) handleUserGroupChange(Number(item.id), Number(v));
2597
+ },
2520
2598
  children: [
2521
- /* @__PURE__ */ jsx22(Eye, { className: "h-4 w-4" }),
2522
- "View"
2599
+ /* @__PURE__ */ jsx22("option", { value: "", children: "\u2014" }),
2600
+ roleOptions.map((g) => /* @__PURE__ */ jsx22("option", { value: g.id, children: g.name }, g.id))
2523
2601
  ]
2524
2602
  }
2525
2603
  ) }),
2526
- !addEditPage && /* @__PURE__ */ jsxs15(DropdownMenuItem, { onClick: () => handleEdit(item), children: [
2527
- /* @__PURE__ */ jsx22(Edit, { className: "h-4 w-4 mr-2" }),
2528
- "Edit"
2529
- ] }),
2530
- addEditPage && /* @__PURE__ */ jsx22(DropdownMenuItem, { asChild: true, children: /* @__PURE__ */ jsxs15(Link4, { href: addEditPageUrl + "/" + item.id, className: "flex items-center gap-2", children: [
2531
- /* @__PURE__ */ jsx22(Edit, { className: "h-4 w-4" }),
2532
- "Edit"
2533
- ] }) }),
2534
- resourceName === "users" && /* @__PURE__ */ jsxs15(DropdownMenuItem, { onClick: () => handleRegenerateInvite(Number(item.id)), children: [
2535
- /* @__PURE__ */ jsx22(RefreshCw, { className: "h-4 w-4 mr-2" }),
2536
- "Regenerate Invite"
2537
- ] }),
2538
- /* @__PURE__ */ jsxs15(
2539
- DropdownMenuItem,
2540
- {
2541
- onClick: () => handleDeleteClick(item),
2542
- className: "text-red-600 focus:text-red-600",
2543
- children: [
2544
- /* @__PURE__ */ jsx22(Trash2, { className: "h-4 w-4 mr-2" }),
2545
- "Delete"
2546
- ]
2547
- }
2548
- )
2549
- ] })
2550
- ] }) })
2551
- ] }, String(item.id ?? index))) : /* @__PURE__ */ jsx22(TableRow, { children: /* @__PURE__ */ jsx22(
2604
+ /* @__PURE__ */ jsx22(TableCell, { className: "text-center", onClick: (e) => e.stopPropagation(), children: /* @__PURE__ */ jsxs15("div", { className: "flex items-center justify-center gap-1", children: [
2605
+ !addEditPage && /* @__PURE__ */ jsxs15(
2606
+ Button,
2607
+ {
2608
+ variant: "outline",
2609
+ size: "icon",
2610
+ className: "h-7 w-7",
2611
+ onClick: () => handleEdit(item),
2612
+ title: "Edit",
2613
+ children: [
2614
+ /* @__PURE__ */ jsx22(Edit, { className: "h-3.5 w-3.5" }),
2615
+ /* @__PURE__ */ jsx22("span", { className: "sr-only", children: "Edit" })
2616
+ ]
2617
+ }
2618
+ ),
2619
+ addEditPage && /* @__PURE__ */ jsxs15(
2620
+ Button,
2621
+ {
2622
+ variant: "outline",
2623
+ size: "icon",
2624
+ className: "h-7 w-7",
2625
+ onClick: () => router.push(addEditPageUrl + "/" + item.id),
2626
+ title: "Edit",
2627
+ children: [
2628
+ /* @__PURE__ */ jsx22(Edit, { className: "h-3.5 w-3.5" }),
2629
+ /* @__PURE__ */ jsx22("span", { className: "sr-only", children: "Edit" })
2630
+ ]
2631
+ }
2632
+ ),
2633
+ resourceName === "users" && /* @__PURE__ */ jsxs15(
2634
+ Button,
2635
+ {
2636
+ variant: "outline",
2637
+ size: "icon",
2638
+ className: "h-7 w-7",
2639
+ onClick: () => handleRegenerateInvite(Number(item.id)),
2640
+ title: "Regenerate Invite",
2641
+ children: [
2642
+ /* @__PURE__ */ jsx22(RefreshCw, { className: "h-3.5 w-3.5" }),
2643
+ /* @__PURE__ */ jsx22("span", { className: "sr-only", children: "Regenerate Invite" })
2644
+ ]
2645
+ }
2646
+ ),
2647
+ /* @__PURE__ */ jsxs15(
2648
+ Button,
2649
+ {
2650
+ variant: "outline",
2651
+ size: "icon",
2652
+ className: "h-7 w-7 border-red-300 text-red-600 hover:text-red-700",
2653
+ onClick: () => handleDeleteClick(item),
2654
+ title: "Delete",
2655
+ children: [
2656
+ /* @__PURE__ */ jsx22(Trash2, { className: "h-3.5 w-3.5" }),
2657
+ /* @__PURE__ */ jsx22("span", { className: "sr-only", children: "Delete" })
2658
+ ]
2659
+ }
2660
+ )
2661
+ ] }) })
2662
+ ]
2663
+ },
2664
+ String(item.id ?? index)
2665
+ )) : /* @__PURE__ */ jsx22(TableRow, { children: /* @__PURE__ */ jsx22(
2552
2666
  TableCell,
2553
2667
  {
2554
2668
  colSpan: columns ? columns.length + 1 + (showGroupColumn ? 1 : 0) : 1,
@@ -2594,21 +2708,35 @@ Note: ${result.note}`);
2594
2708
  existingData: editingItem
2595
2709
  }
2596
2710
  ),
2597
- /* @__PURE__ */ jsx22(Dialog, { open: deleteDialogOpen, onOpenChange: setDeleteDialogOpen, children: /* @__PURE__ */ jsxs15(DialogContent, { children: [
2598
- /* @__PURE__ */ jsxs15(DialogHeader, { children: [
2599
- /* @__PURE__ */ jsx22(DialogTitle, { children: "Confirm Delete" }),
2600
- /* @__PURE__ */ jsx22(DialogDescription, { children: "Are you sure you want to delete this item? This action cannot be undone." }),
2601
- itemToDelete && /* @__PURE__ */ jsxs15("div", { className: "mt-2 p-2 bg-gray-50 rounded", children: [
2602
- /* @__PURE__ */ jsx22("strong", { children: "Item:" }),
2603
- " ",
2604
- String(itemToDelete.name ?? itemToDelete.title ?? itemToDelete.id ?? "")
2711
+ /* @__PURE__ */ jsx22(
2712
+ Dialog,
2713
+ {
2714
+ open: deleteDialogOpen,
2715
+ onOpenChange: (open) => {
2716
+ console.debug("[CRUD][delete] dialog onOpenChange", {
2717
+ nextOpen: open,
2718
+ itemId: itemToDelete?.id
2719
+ });
2720
+ if (!open) closeDeleteDialog();
2721
+ else setDeleteDialogOpen(true);
2722
+ },
2723
+ children: /* @__PURE__ */ jsxs15(DialogContent, { children: [
2724
+ /* @__PURE__ */ jsxs15(DialogHeader, { children: [
2725
+ /* @__PURE__ */ jsx22(DialogTitle, { children: "Confirm Delete" }),
2726
+ /* @__PURE__ */ jsx22(DialogDescription, { children: "Are you sure you want to delete this item? This action cannot be undone." }),
2727
+ itemToDelete && /* @__PURE__ */ jsxs15("div", { className: "mt-2 p-2 bg-gray-50 rounded", children: [
2728
+ /* @__PURE__ */ jsx22("strong", { children: "Item:" }),
2729
+ " ",
2730
+ String(itemToDelete.name ?? itemToDelete.title ?? itemToDelete.id ?? "")
2731
+ ] })
2732
+ ] }),
2733
+ /* @__PURE__ */ jsxs15(DialogFooter, { children: [
2734
+ /* @__PURE__ */ jsx22(Button, { variant: "outline", onClick: closeDeleteDialog, disabled: deleteLoading, children: "Cancel" }),
2735
+ /* @__PURE__ */ jsx22(Button, { variant: "destructive", onClick: handleDelete, disabled: deleteLoading, children: deleteLoading ? "Deleting..." : "Delete" })
2736
+ ] })
2605
2737
  ] })
2606
- ] }),
2607
- /* @__PURE__ */ jsxs15(DialogFooter, { children: [
2608
- /* @__PURE__ */ jsx22(Button, { variant: "outline", onClick: () => setDeleteDialogOpen(false), disabled: deleteLoading, children: "Cancel" }),
2609
- /* @__PURE__ */ jsx22(Button, { variant: "destructive", onClick: handleDelete, disabled: deleteLoading, children: deleteLoading ? "Deleting..." : "Delete" })
2610
- ] })
2611
- ] }) }),
2738
+ }
2739
+ ),
2612
2740
  bulkDialogOpen && /* @__PURE__ */ jsx22(
2613
2741
  BulkUploadDialog,
2614
2742
  {
@@ -2624,7 +2752,7 @@ Note: ${result.note}`);
2624
2752
  }
2625
2753
 
2626
2754
  // src/components/Admin/FormBuilder.tsx
2627
- import { useState as useState9, useEffect as useEffect7, useCallback as useCallback2 } from "react";
2755
+ import { useState as useState10, useEffect as useEffect7, useCallback as useCallback2 } from "react";
2628
2756
 
2629
2757
  // src/components/ui/badge.tsx
2630
2758
  import { cva as cva4 } from "class-variance-authority";
@@ -2650,11 +2778,11 @@ function Badge({ className, variant, ...props }) {
2650
2778
  }
2651
2779
 
2652
2780
  // src/components/Admin/FormBuilder.tsx
2653
- import { X as X7, Save, Plus as Plus3, Trash2 as Trash22 } from "lucide-react";
2654
- import { useRouter as useRouter2 } from "next/navigation";
2781
+ import { X as X7, Save, Plus as Plus3, Trash2 as Trash22, Check as Check4 } from "lucide-react";
2782
+ import { useRouter as useRouter3 } from "next/navigation";
2655
2783
 
2656
2784
  // src/components/Admin/FormBuilder/FieldConfiguration.tsx
2657
- import { useState as useState8 } from "react";
2785
+ import { useState as useState9 } from "react";
2658
2786
  import { Plus as Plus2, X as X6 } from "lucide-react";
2659
2787
  import { jsx as jsx24, jsxs as jsxs16 } from "react/jsx-runtime";
2660
2788
  var FIELD_TYPES = [
@@ -2675,7 +2803,7 @@ var COLUMN_WIDTHS = [
2675
2803
  { value: 12, label: "Full Width (12 cols)" }
2676
2804
  ];
2677
2805
  function FieldConfiguration({ field, onUpdate }) {
2678
- const [newOption, setNewOption] = useState8("");
2806
+ const [newOption, setNewOption] = useState9("");
2679
2807
  const addOption = () => {
2680
2808
  if (newOption.trim()) {
2681
2809
  const currentOptions = field.options || [];
@@ -2948,7 +3076,7 @@ function FieldConfiguration({ field, onUpdate }) {
2948
3076
  // src/components/Admin/FormBuilder.tsx
2949
3077
  import { jsx as jsx25, jsxs as jsxs17 } from "react/jsx-runtime";
2950
3078
  function FormBuilder({ formId }) {
2951
- const [formData, setFormData] = useState9({
3079
+ const [formData, setFormData] = useState10({
2952
3080
  name: "",
2953
3081
  description: "",
2954
3082
  campaign: "",
@@ -2956,11 +3084,11 @@ function FormBuilder({ formId }) {
2956
3084
  published: false,
2957
3085
  fields: []
2958
3086
  });
2959
- const [errors, setErrors] = useState9([]);
2960
- const [isLoading, setIsLoading] = useState9(false);
2961
- const [isSaving, setIsSaving] = useState9(false);
2962
- const [selectedField, setSelectedField] = useState9(null);
2963
- const router = useRouter2();
3087
+ const [errors, setErrors] = useState10([]);
3088
+ const [isLoading, setIsLoading] = useState10(false);
3089
+ const [isSaving, setIsSaving] = useState10(false);
3090
+ const [selectedField, setSelectedField] = useState10(null);
3091
+ const router = useRouter3();
2964
3092
  const loadFormData = useCallback2(async () => {
2965
3093
  try {
2966
3094
  setIsLoading(true);
@@ -3125,19 +3253,34 @@ function FormBuilder({ formId }) {
3125
3253
  /* @__PURE__ */ jsx25("h1", { className: "text-xl font-bold text-white", children: formId ? "Edit Form" : "Create New Form" }),
3126
3254
  /* @__PURE__ */ jsx25("p", { className: "text-xs text-gray-300 mt-0.5", children: "Design your form with drag-and-drop fields" })
3127
3255
  ] }),
3128
- /* @__PURE__ */ jsx25("div", { className: "flex items-center space-x-3", children: /* @__PURE__ */ jsxs17(
3129
- Button,
3130
- {
3131
- variant: "outline",
3132
- size: "sm",
3133
- className: "bg-white text-gray-800 hover:bg-gray-100 border-0 text-xs",
3134
- onClick: () => router.push("/admin/forms"),
3135
- children: [
3136
- /* @__PURE__ */ jsx25(X7, { className: "h-4 w-4 mr-2" }),
3137
- "Close"
3138
- ]
3139
- }
3140
- ) })
3256
+ /* @__PURE__ */ jsxs17("div", { className: "flex items-center space-x-3", children: [
3257
+ /* @__PURE__ */ jsxs17(
3258
+ Button,
3259
+ {
3260
+ variant: "outline",
3261
+ size: "icon",
3262
+ className: "md:hidden h-8 w-8 bg-white text-gray-800 hover:bg-gray-100 border-0",
3263
+ onClick: () => router.push("/admin/forms"),
3264
+ children: [
3265
+ /* @__PURE__ */ jsx25(X7, { className: "h-4 w-4" }),
3266
+ /* @__PURE__ */ jsx25("span", { className: "sr-only", children: "Close" })
3267
+ ]
3268
+ }
3269
+ ),
3270
+ /* @__PURE__ */ jsxs17(
3271
+ Button,
3272
+ {
3273
+ variant: "outline",
3274
+ size: "sm",
3275
+ className: "hidden md:inline-flex bg-white text-gray-800 hover:bg-gray-100 border-0 text-xs",
3276
+ onClick: () => router.push("/admin/forms"),
3277
+ children: [
3278
+ /* @__PURE__ */ jsx25(X7, { className: "h-4 w-4 mr-2" }),
3279
+ "Close"
3280
+ ]
3281
+ }
3282
+ )
3283
+ ] })
3141
3284
  ] }) }),
3142
3285
  errors.length > 0 && /* @__PURE__ */ jsx25("div", { className: "bg-red-50 border-l-4 border-red-400 p-4 mx-6 mt-4", children: /* @__PURE__ */ jsx25("div", { className: "flex", children: /* @__PURE__ */ jsxs17("div", { className: "ml-3", children: [
3143
3286
  /* @__PURE__ */ jsx25("h3", { className: "text-sm font-medium text-red-800", children: "Please fix the following errors:" }),
@@ -3315,11 +3458,24 @@ function FormBuilder({ formId }) {
3315
3458
  /* @__PURE__ */ jsx25("div", { className: "bg-gray-50 border-t border-gray-200 px-6 py-4", children: /* @__PURE__ */ jsxs17("div", { className: "flex items-center justify-between", children: [
3316
3459
  /* @__PURE__ */ jsx25("div", { className: "text-sm text-gray-600", children: formId ? "Editing existing form" : "Creating new form" }),
3317
3460
  /* @__PURE__ */ jsxs17("div", { className: "flex items-center space-x-3", children: [
3461
+ /* @__PURE__ */ jsxs17(
3462
+ Button,
3463
+ {
3464
+ variant: "outline",
3465
+ size: "icon",
3466
+ className: "md:hidden h-8 w-8 bg-white text-gray-800 hover:bg-gray-100 border-0",
3467
+ onClick: () => router.push("/admin/forms"),
3468
+ children: [
3469
+ /* @__PURE__ */ jsx25(X7, { className: "h-4 w-4" }),
3470
+ /* @__PURE__ */ jsx25("span", { className: "sr-only", children: "Close" })
3471
+ ]
3472
+ }
3473
+ ),
3318
3474
  /* @__PURE__ */ jsx25(
3319
3475
  Button,
3320
3476
  {
3321
3477
  variant: "outline",
3322
- className: "bg-white text-gray-800 hover:bg-gray-100 border-0 text-xs",
3478
+ className: "hidden md:inline-flex bg-white text-gray-800 hover:bg-gray-100 border-0 text-xs",
3323
3479
  onClick: () => router.push("/admin/forms"),
3324
3480
  children: "Close"
3325
3481
  }
@@ -3329,19 +3485,45 @@ function FormBuilder({ formId }) {
3329
3485
  {
3330
3486
  onClick: () => handleSave(false),
3331
3487
  disabled: isSaving,
3332
- className: "bg-white text-gray-800 hover:bg-gray-100 border-0 text-xs",
3488
+ size: "icon",
3489
+ className: "md:hidden h-8 w-8 bg-white text-gray-800 hover:bg-gray-100 border-0",
3490
+ children: [
3491
+ /* @__PURE__ */ jsx25(Save, { className: "h-4 w-4" }),
3492
+ /* @__PURE__ */ jsx25("span", { className: "sr-only", children: isSaving ? "Saving..." : "Save" })
3493
+ ]
3494
+ }
3495
+ ),
3496
+ /* @__PURE__ */ jsxs17(
3497
+ Button,
3498
+ {
3499
+ onClick: () => handleSave(false),
3500
+ disabled: isSaving,
3501
+ className: "hidden md:inline-flex bg-white text-gray-800 hover:bg-gray-100 border-0 text-xs",
3333
3502
  children: [
3334
3503
  /* @__PURE__ */ jsx25(Save, { className: "h-4 w-4 mr-2" }),
3335
3504
  isSaving ? "Saving..." : "Save"
3336
3505
  ]
3337
3506
  }
3338
3507
  ),
3508
+ /* @__PURE__ */ jsxs17(
3509
+ Button,
3510
+ {
3511
+ onClick: () => handleSave(true),
3512
+ disabled: isSaving,
3513
+ size: "icon",
3514
+ className: "md:hidden h-8 w-8 bg-gray-800 text-white hover:bg-gray-700",
3515
+ children: [
3516
+ /* @__PURE__ */ jsx25(Check4, { className: "h-4 w-4" }),
3517
+ /* @__PURE__ */ jsx25("span", { className: "sr-only", children: isSaving ? "Publishing..." : "Publish" })
3518
+ ]
3519
+ }
3520
+ ),
3339
3521
  /* @__PURE__ */ jsx25(
3340
3522
  Button,
3341
3523
  {
3342
3524
  onClick: () => handleSave(true),
3343
3525
  disabled: isSaving,
3344
- className: "bg-gray-800 text-white hover:bg-gray-700 text-xs",
3526
+ className: "hidden md:inline-flex bg-gray-800 text-white hover:bg-gray-700 text-xs",
3345
3527
  children: isSaving ? "Publishing..." : "Publish"
3346
3528
  }
3347
3529
  )
@@ -3351,10 +3533,10 @@ function FormBuilder({ formId }) {
3351
3533
  }
3352
3534
 
3353
3535
  // src/components/Admin/BlogEditorPage.tsx
3354
- import { useState as useState14, useEffect as useEffect11 } from "react";
3536
+ import { useState as useState15, useEffect as useEffect11 } from "react";
3355
3537
 
3356
3538
  // src/components/ui/image-upload.tsx
3357
- import { useState as useState10, useRef as useRef3, useCallback as useCallback3 } from "react";
3539
+ import { useState as useState11, useRef as useRef4, useCallback as useCallback3 } from "react";
3358
3540
  import { Upload as Upload3, X as X8, ImageIcon as ImageIcon2, AlertCircle as AlertCircle2 } from "lucide-react";
3359
3541
  import Image3 from "next/image";
3360
3542
  import { jsx as jsx26, jsxs as jsxs18 } from "react/jsx-runtime";
@@ -3369,11 +3551,11 @@ function ImageUpload({
3369
3551
  // 10MB default
3370
3552
  acceptedTypes = ["image/jpeg", "image/png", "image/gif", "image/webp"]
3371
3553
  }) {
3372
- const [isDragOver, setIsDragOver] = useState10(false);
3373
- const [isUploading, setIsUploading] = useState10(false);
3374
- const [uploadProgress, setUploadProgress] = useState10(0);
3375
- const [error, setError] = useState10(null);
3376
- const fileInputRef = useRef3(null);
3554
+ const [isDragOver, setIsDragOver] = useState11(false);
3555
+ const [isUploading, setIsUploading] = useState11(false);
3556
+ const [uploadProgress, setUploadProgress] = useState11(0);
3557
+ const [error, setError] = useState11(null);
3558
+ const fileInputRef = useRef4(null);
3377
3559
  const handleFileSelect = useCallback3(async (file) => {
3378
3560
  setError(null);
3379
3561
  setUploadProgress(0);
@@ -3555,10 +3737,10 @@ function ImageUpload({
3555
3737
 
3556
3738
  // src/components/Admin/BlogEditorPage.tsx
3557
3739
  import { X as X12, Save as Save2, AlertCircle as AlertCircle3 } from "lucide-react";
3558
- import { useRouter as useRouter3 } from "next/navigation";
3740
+ import { useRouter as useRouter4 } from "next/navigation";
3559
3741
 
3560
3742
  // src/components/Admin/TagAutocomplete.tsx
3561
- import { useState as useState11, useEffect as useEffect8, useRef as useRef4, useCallback as useCallback4 } from "react";
3743
+ import { useState as useState12, useEffect as useEffect8, useRef as useRef5, useCallback as useCallback4 } from "react";
3562
3744
  import { X as X9, Plus as Plus4, Search as Search2 } from "lucide-react";
3563
3745
  import { Fragment as Fragment4, jsx as jsx27, jsxs as jsxs19 } from "react/jsx-runtime";
3564
3746
  function TagAutocomplete({
@@ -3567,13 +3749,13 @@ function TagAutocomplete({
3567
3749
  placeholder = "Search or create tags...",
3568
3750
  className = ""
3569
3751
  }) {
3570
- const [inputValue, setInputValue] = useState11("");
3571
- const [suggestions, setSuggestions] = useState11([]);
3572
- const [isLoading, setIsLoading] = useState11(false);
3573
- const [showSuggestions, setShowSuggestions] = useState11(false);
3574
- const [isCreating, setIsCreating] = useState11(false);
3575
- const inputRef = useRef4(null);
3576
- const suggestionsRef = useRef4(null);
3752
+ const [inputValue, setInputValue] = useState12("");
3753
+ const [suggestions, setSuggestions] = useState12([]);
3754
+ const [isLoading, setIsLoading] = useState12(false);
3755
+ const [showSuggestions, setShowSuggestions] = useState12(false);
3756
+ const [isCreating, setIsCreating] = useState12(false);
3757
+ const inputRef = useRef5(null);
3758
+ const suggestionsRef = useRef5(null);
3577
3759
  const fetchSuggestions = useCallback4(async (query) => {
3578
3760
  if (!query.trim()) {
3579
3761
  setSuggestions([]);
@@ -3719,7 +3901,10 @@ function TagAutocomplete({
3719
3901
  "div",
3720
3902
  {
3721
3903
  className: "px-4 py-2 hover:bg-gray-100 cursor-pointer text-sm",
3722
- onClick: () => handleSuggestionSelect(tag),
3904
+ onMouseDown: (e) => {
3905
+ e.preventDefault();
3906
+ handleSuggestionSelect(tag);
3907
+ },
3723
3908
  children: tag.name
3724
3909
  },
3725
3910
  tag.id
@@ -3735,7 +3920,10 @@ function TagAutocomplete({
3735
3920
  "div",
3736
3921
  {
3737
3922
  className: "px-4 py-2 hover:bg-gray-100 cursor-pointer text-sm text-gray-700 flex items-center",
3738
- onClick: handleCreateTag,
3923
+ onMouseDown: (e) => {
3924
+ e.preventDefault();
3925
+ handleCreateTag();
3926
+ },
3739
3927
  children: [
3740
3928
  /* @__PURE__ */ jsx27(Plus4, { className: "h-3 w-3 mr-2" }),
3741
3929
  'Create "',
@@ -3751,7 +3939,7 @@ function TagAutocomplete({
3751
3939
 
3752
3940
  // src/components/Admin/JoditRichText.tsx
3753
3941
  import dynamic from "next/dynamic";
3754
- import { useMemo } from "react";
3942
+ import { useMemo as useMemo2 } from "react";
3755
3943
  import "jodit/es2021/jodit.min.css";
3756
3944
  import { jsx as jsx28 } from "react/jsx-runtime";
3757
3945
  var JoditEditor = dynamic(() => import("jodit-react").then((m) => m.default), {
@@ -3759,7 +3947,7 @@ var JoditEditor = dynamic(() => import("jodit-react").then((m) => m.default), {
3759
3947
  loading: () => /* @__PURE__ */ jsx28("div", { className: "min-h-[300px] rounded-md border border-gray-200 bg-gray-50 animate-pulse" })
3760
3948
  });
3761
3949
  function JoditRichText({ value, onChange, placeholder, minHeight = 400 }) {
3762
- const config = useMemo(
3950
+ const config = useMemo2(
3763
3951
  () => ({
3764
3952
  readonly: false,
3765
3953
  placeholder: placeholder ?? "",
@@ -3823,8 +4011,8 @@ function JoditRichText({ value, onChange, placeholder, minHeight = 400 }) {
3823
4011
  }
3824
4012
 
3825
4013
  // src/components/Admin/CategoryAutocomplete.tsx
3826
- import { useState as useState12, useEffect as useEffect9, useRef as useRef5 } from "react";
3827
- import { X as X10, Plus as Plus5, Search as Search3, Check as Check4 } from "lucide-react";
4014
+ import { useState as useState13, useEffect as useEffect9, useRef as useRef6 } from "react";
4015
+ import { X as X10, Plus as Plus5, Search as Search3, Check as Check5 } from "lucide-react";
3828
4016
  import { Fragment as Fragment5, jsx as jsx29, jsxs as jsxs20 } from "react/jsx-runtime";
3829
4017
  function CategoryAutocomplete({
3830
4018
  selectedCategory,
@@ -3832,13 +4020,13 @@ function CategoryAutocomplete({
3832
4020
  placeholder = "Search or create category...",
3833
4021
  className = ""
3834
4022
  }) {
3835
- const [inputValue, setInputValue] = useState12("");
3836
- const [suggestions, setSuggestions] = useState12([]);
3837
- const [isLoading, setIsLoading] = useState12(false);
3838
- const [showSuggestions, setShowSuggestions] = useState12(false);
3839
- const [isCreating, setIsCreating] = useState12(false);
3840
- const inputRef = useRef5(null);
3841
- const suggestionsRef = useRef5(null);
4023
+ const [inputValue, setInputValue] = useState13("");
4024
+ const [suggestions, setSuggestions] = useState13([]);
4025
+ const [isLoading, setIsLoading] = useState13(false);
4026
+ const [showSuggestions, setShowSuggestions] = useState13(false);
4027
+ const [isCreating, setIsCreating] = useState13(false);
4028
+ const inputRef = useRef6(null);
4029
+ const suggestionsRef = useRef6(null);
3842
4030
  const fetchSuggestions = async (query) => {
3843
4031
  if (!query.trim()) {
3844
4032
  setSuggestions([]);
@@ -3979,10 +4167,13 @@ function CategoryAutocomplete({
3979
4167
  "div",
3980
4168
  {
3981
4169
  className: "px-4 py-2 hover:bg-gray-100 cursor-pointer text-sm flex items-center justify-between",
3982
- onClick: () => handleSuggestionSelect(category),
4170
+ onMouseDown: (e) => {
4171
+ e.preventDefault();
4172
+ handleSuggestionSelect(category);
4173
+ },
3983
4174
  children: [
3984
4175
  category.name,
3985
- selectedCategory === category.name && /* @__PURE__ */ jsx29(Check4, { className: "h-4 w-4 text-green-500" })
4176
+ selectedCategory === category.name && /* @__PURE__ */ jsx29(Check5, { className: "h-4 w-4 text-green-500" })
3986
4177
  ]
3987
4178
  },
3988
4179
  category.id
@@ -3998,7 +4189,10 @@ function CategoryAutocomplete({
3998
4189
  "div",
3999
4190
  {
4000
4191
  className: "px-4 py-2 hover:bg-gray-100 cursor-pointer text-sm text-gray-700 flex items-center",
4001
- onClick: handleCreateCategory,
4192
+ onMouseDown: (e) => {
4193
+ e.preventDefault();
4194
+ handleCreateCategory();
4195
+ },
4002
4196
  children: [
4003
4197
  /* @__PURE__ */ jsx29(Plus5, { className: "h-3 w-3 mr-2" }),
4004
4198
  'Create "',
@@ -4013,8 +4207,8 @@ function CategoryAutocomplete({
4013
4207
  }
4014
4208
 
4015
4209
  // src/components/Admin/UserAutocomplete.tsx
4016
- import { useState as useState13, useEffect as useEffect10, useRef as useRef6 } from "react";
4017
- import { X as X11, Search as Search4, Check as Check5 } from "lucide-react";
4210
+ import { useState as useState14, useEffect as useEffect10, useRef as useRef7 } from "react";
4211
+ import { X as X11, Search as Search4, Check as Check6 } from "lucide-react";
4018
4212
  import { jsx as jsx30, jsxs as jsxs21 } from "react/jsx-runtime";
4019
4213
  function UserAutocomplete({
4020
4214
  selectedUserId,
@@ -4022,12 +4216,12 @@ function UserAutocomplete({
4022
4216
  placeholder = "Select author...",
4023
4217
  className = ""
4024
4218
  }) {
4025
- const [inputValue, setInputValue] = useState13("");
4026
- const [suggestions, setSuggestions] = useState13([]);
4027
- const [isLoading, setIsLoading] = useState13(false);
4028
- const [showSuggestions, setShowSuggestions] = useState13(false);
4029
- const inputRef = useRef6(null);
4030
- const suggestionsRef = useRef6(null);
4219
+ const [inputValue, setInputValue] = useState14("");
4220
+ const [suggestions, setSuggestions] = useState14([]);
4221
+ const [isLoading, setIsLoading] = useState14(false);
4222
+ const [showSuggestions, setShowSuggestions] = useState14(false);
4223
+ const inputRef = useRef7(null);
4224
+ const suggestionsRef = useRef7(null);
4031
4225
  const fetchSuggestions = async (query) => {
4032
4226
  setIsLoading(true);
4033
4227
  try {
@@ -4125,13 +4319,16 @@ function UserAutocomplete({
4125
4319
  "div",
4126
4320
  {
4127
4321
  className: "px-4 py-2 hover:bg-gray-100 cursor-pointer text-sm flex items-center justify-between",
4128
- onClick: () => handleSuggestionSelect(user),
4322
+ onMouseDown: (e) => {
4323
+ e.preventDefault();
4324
+ handleSuggestionSelect(user);
4325
+ },
4129
4326
  children: [
4130
4327
  /* @__PURE__ */ jsxs21("div", { className: "flex flex-col", children: [
4131
4328
  /* @__PURE__ */ jsx30("span", { className: "font-medium", children: user.name }),
4132
4329
  /* @__PURE__ */ jsx30("span", { className: "text-xs text-gray-500", children: user.email })
4133
4330
  ] }),
4134
- selectedUserId === user.id && /* @__PURE__ */ jsx30(Check5, { className: "h-4 w-4 text-green-500" })
4331
+ selectedUserId === user.id && /* @__PURE__ */ jsx30(Check6, { className: "h-4 w-4 text-green-500" })
4135
4332
  ]
4136
4333
  },
4137
4334
  user.id
@@ -4144,39 +4341,39 @@ function UserAutocomplete({
4144
4341
  // src/components/Admin/BlogEditorPage.tsx
4145
4342
  import { jsx as jsx31, jsxs as jsxs22 } from "react/jsx-runtime";
4146
4343
  function BlogEditor({ existingBlog }) {
4147
- const [title, setTitle] = useState14(existingBlog?.title || "");
4148
- const [slug, setSlug] = useState14(existingBlog?.slug || "");
4149
- const [coverImage, setCoverImage] = useState14(
4344
+ const [title, setTitle] = useState15(existingBlog?.title || "");
4345
+ const [slug, setSlug] = useState15(existingBlog?.slug || "");
4346
+ const [coverImage, setCoverImage] = useState15(
4150
4347
  existingBlog?.coverImage || null
4151
4348
  );
4152
- const [ogImage, setOgImage] = useState14(
4349
+ const [ogImage, setOgImage] = useState15(
4153
4350
  existingBlog?.seo?.ogImage || existingBlog?.ogImage || null
4154
4351
  );
4155
- const [metaTitle, setMetaTitle] = useState14(existingBlog?.seo?.title || "");
4156
- const [metaDescription, setMetaDescription] = useState14(
4352
+ const [metaTitle, setMetaTitle] = useState15(existingBlog?.seo?.title || "");
4353
+ const [metaDescription, setMetaDescription] = useState15(
4157
4354
  existingBlog?.seo?.description || ""
4158
4355
  );
4159
- const [metaKeywords, setMetaKeywords] = useState14(
4356
+ const [metaKeywords, setMetaKeywords] = useState15(
4160
4357
  existingBlog?.seo?.keywords || ""
4161
4358
  );
4162
- const [published, setPublished] = useState14(existingBlog?.published || false);
4163
- const [tags, setTags] = useState14(
4359
+ const [published, setPublished] = useState15(existingBlog?.published || false);
4360
+ const [tags, setTags] = useState15(
4164
4361
  existingBlog?.tags?.map((tag) => tag.name) || []
4165
4362
  );
4166
- const [category, setCategory] = useState14(
4363
+ const [category, setCategory] = useState15(
4167
4364
  existingBlog?.category?.name || null
4168
4365
  );
4169
- const [authorId, setAuthorId] = useState14(
4366
+ const [authorId, setAuthorId] = useState15(
4170
4367
  existingBlog?.authorId || null
4171
4368
  );
4172
- const [content, setContent] = useState14(existingBlog?.content || "");
4173
- const [createdAt, setCreatedAt] = useState14(
4369
+ const [content, setContent] = useState15(existingBlog?.content || "");
4370
+ const [createdAt, setCreatedAt] = useState15(
4174
4371
  existingBlog?.createdAt ? new Date(existingBlog.createdAt).toISOString().slice(0, 16) : (/* @__PURE__ */ new Date()).toISOString().slice(0, 16)
4175
4372
  );
4176
- const [errors, setErrors] = useState14([]);
4177
- const [isLoading, setIsLoading] = useState14(false);
4178
- const [isSaving, setIsSaving] = useState14(false);
4179
- const router = useRouter3();
4373
+ const [errors, setErrors] = useState15([]);
4374
+ const [isLoading, setIsLoading] = useState15(false);
4375
+ const [isSaving, setIsSaving] = useState15(false);
4376
+ const router = useRouter4();
4180
4377
  useEffect11(() => {
4181
4378
  if (title && !slug) {
4182
4379
  const generatedSlug = title.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/(^-|-$)/g, "");
@@ -4302,11 +4499,25 @@ function BlogEditor({ existingBlog }) {
4302
4499
  ),
4303
4500
  /* @__PURE__ */ jsx31("span", { className: "text-xs text-gray-300", children: "Published" })
4304
4501
  ] }),
4502
+ /* @__PURE__ */ jsxs22(
4503
+ Button,
4504
+ {
4505
+ size: "icon",
4506
+ className: "md:hidden h-8 w-8 bg-white text-gray-800 hover:bg-gray-100 border-0",
4507
+ onClick: () => handleSave(published),
4508
+ disabled: isSaving,
4509
+ title: isSaving ? "Saving..." : "Save",
4510
+ children: [
4511
+ /* @__PURE__ */ jsx31(Save2, { className: "h-4 w-4" }),
4512
+ /* @__PURE__ */ jsx31("span", { className: "sr-only", children: isSaving ? "Saving..." : "Save" })
4513
+ ]
4514
+ }
4515
+ ),
4305
4516
  /* @__PURE__ */ jsxs22(
4306
4517
  Button,
4307
4518
  {
4308
4519
  size: "sm",
4309
- className: "flex items-center bg-white text-gray-800 hover:bg-gray-100 border-0 text-xs",
4520
+ className: "hidden md:inline-flex items-center bg-white text-gray-800 hover:bg-gray-100 border-0 text-xs",
4310
4521
  onClick: () => handleSave(published),
4311
4522
  disabled: isSaving,
4312
4523
  children: [
@@ -4315,12 +4526,26 @@ function BlogEditor({ existingBlog }) {
4315
4526
  ]
4316
4527
  }
4317
4528
  ),
4529
+ /* @__PURE__ */ jsxs22(
4530
+ Button,
4531
+ {
4532
+ variant: "outline",
4533
+ size: "icon",
4534
+ className: "md:hidden h-8 w-8 bg-white text-gray-800 hover:bg-gray-100 border-0",
4535
+ onClick: () => router.back(),
4536
+ title: "Close",
4537
+ children: [
4538
+ /* @__PURE__ */ jsx31(X12, { className: "h-4 w-4" }),
4539
+ /* @__PURE__ */ jsx31("span", { className: "sr-only", children: "Close" })
4540
+ ]
4541
+ }
4542
+ ),
4318
4543
  /* @__PURE__ */ jsxs22(
4319
4544
  Button,
4320
4545
  {
4321
4546
  variant: "outline",
4322
4547
  size: "sm",
4323
- className: "flex items-center bg-white text-gray-800 hover:bg-gray-100 border-0 text-xs",
4548
+ className: "hidden md:inline-flex items-center bg-white text-gray-800 hover:bg-gray-100 border-0 text-xs",
4324
4549
  onClick: () => router.back(),
4325
4550
  children: [
4326
4551
  /* @__PURE__ */ jsx31(X12, { className: "h-4 w-4 mr-1" }),
@@ -4502,10 +4727,10 @@ function BlogEditor({ existingBlog }) {
4502
4727
  }
4503
4728
 
4504
4729
  // src/components/Admin/AnalyticsChart.tsx
4505
- import { useEffect as useEffect12, useRef as useRef7 } from "react";
4730
+ import { useEffect as useEffect12, useRef as useRef8 } from "react";
4506
4731
  import { jsx as jsx32, jsxs as jsxs23 } from "react/jsx-runtime";
4507
4732
  function AnalyticsChart({ data, title, type }) {
4508
- const canvasRef = useRef7(null);
4733
+ const canvasRef = useRef8(null);
4509
4734
  useEffect12(() => {
4510
4735
  if (!canvasRef.current || !data.length) return;
4511
4736
  const ctx = canvasRef.current.getContext("2d");
@@ -4741,14 +4966,14 @@ function AnalyticsExclusion() {
4741
4966
  }
4742
4967
 
4743
4968
  // src/components/Admin/ComponentSettings.tsx
4744
- import { useState as useState15, useEffect as useEffect14 } from "react";
4969
+ import { useState as useState16, useEffect as useEffect14 } from "react";
4745
4970
  import { jsx as jsx37, jsxs as jsxs28 } from "react/jsx-runtime";
4746
4971
  function EntitySelect({
4747
4972
  prop,
4748
4973
  value,
4749
4974
  onChange
4750
4975
  }) {
4751
- const [options, setOptions] = useState15([]);
4976
+ const [options, setOptions] = useState16([]);
4752
4977
  useEffect14(() => {
4753
4978
  if (!prop.entity) return;
4754
4979
  fetch(`/api/${prop.entity}`).then((r) => r.ok ? r.json() : { data: [] }).then((res) => setOptions(res.data || res || [])).catch(() => {
@@ -4887,7 +5112,7 @@ function ComponentSettings({
4887
5112
  }
4888
5113
 
4889
5114
  // src/components/Admin/NavbarEditor.tsx
4890
- import { useState as useState16, useEffect as useEffect15 } from "react";
5115
+ import { useState as useState17, useEffect as useEffect15 } from "react";
4891
5116
  import { Plus as Plus6, Trash2 as Trash23, GripVertical, ChevronDown as ChevronDown4, ChevronRight as ChevronRight3, ArrowRight, ArrowLeft as ArrowLeft3 } from "lucide-react";
4892
5117
  import { jsx as jsx38, jsxs as jsxs29 } from "react/jsx-runtime";
4893
5118
  function generateId() {
@@ -4907,8 +5132,8 @@ function NavItemEditor({
4907
5132
  canMoveUp,
4908
5133
  canMoveDown
4909
5134
  }) {
4910
- const [expanded, setExpanded] = useState16(false);
4911
- const [pages, setPages] = useState16([]);
5135
+ const [expanded, setExpanded] = useState17(false);
5136
+ const [pages, setPages] = useState17([]);
4912
5137
  useEffect15(() => {
4913
5138
  if (!expanded) return;
4914
5139
  fetch("/api/pages").then((r) => r.ok ? r.json() : []).then((data) => {
@@ -5177,9 +5402,9 @@ function NavbarEditor({ config, onChange }) {
5177
5402
 
5178
5403
  // src/admin/pages/SignInPage.tsx
5179
5404
  import Link5 from "next/link";
5180
- import { useState as useState17, useEffect as useEffect16 } from "react";
5405
+ import { useState as useState18, useEffect as useEffect16 } from "react";
5181
5406
  import { signIn, useSession as useSession3 } from "next-auth/react";
5182
- import { useRouter as useRouter4 } from "next/navigation";
5407
+ import { useRouter as useRouter5 } from "next/navigation";
5183
5408
 
5184
5409
  // src/components/Admin/AuthPageLayout.tsx
5185
5410
  import Image5 from "next/image";
@@ -5237,11 +5462,11 @@ function AuthPageLayout({ children }) {
5237
5462
  // src/admin/pages/SignInPage.tsx
5238
5463
  import { jsx as jsx41, jsxs as jsxs32 } from "react/jsx-runtime";
5239
5464
  var SigninPage = () => {
5240
- const [email, setEmail] = useState17("");
5241
- const [password, setPassword] = useState17("");
5242
- const [error, setError] = useState17("");
5243
- const [loading, setLoading] = useState17(false);
5244
- const router = useRouter4();
5465
+ const [email, setEmail] = useState18("");
5466
+ const [password, setPassword] = useState18("");
5467
+ const [error, setError] = useState18("");
5468
+ const [loading, setLoading] = useState18(false);
5469
+ const router = useRouter5();
5245
5470
  const { status } = useSession3();
5246
5471
  useEffect16(() => {
5247
5472
  if (status === "authenticated") {
@@ -5326,13 +5551,13 @@ var SigninPage = () => {
5326
5551
  var SignInPage_default = SigninPage;
5327
5552
 
5328
5553
  // src/admin/pages/ForgotPasswordPage.tsx
5329
- import { useState as useState18 } from "react";
5554
+ import { useState as useState19 } from "react";
5330
5555
  import Link6 from "next/link";
5331
5556
  import { jsx as jsx42, jsxs as jsxs33 } from "react/jsx-runtime";
5332
5557
  function ForgotPasswordPage() {
5333
- const [email, setEmail] = useState18("");
5334
- const [loading, setLoading] = useState18(false);
5335
- const [message, setMessage] = useState18("");
5558
+ const [email, setEmail] = useState19("");
5559
+ const [loading, setLoading] = useState19(false);
5560
+ const [message, setMessage] = useState19("");
5336
5561
  const handleSubmit = async (e) => {
5337
5562
  e.preventDefault();
5338
5563
  if (!email.trim()) return;
@@ -5374,16 +5599,16 @@ function ForgotPasswordPage() {
5374
5599
  }
5375
5600
 
5376
5601
  // src/admin/pages/ResetPasswordPage.tsx
5377
- import { useState as useState19, useEffect as useEffect17, Suspense } from "react";
5602
+ import { useState as useState20, useEffect as useEffect17, Suspense } from "react";
5378
5603
  import { useSearchParams } from "next/navigation";
5379
5604
  import Link7 from "next/link";
5380
5605
  import { jsx as jsx43, jsxs as jsxs34 } from "react/jsx-runtime";
5381
5606
  function ResetPasswordPageContent() {
5382
5607
  const searchParams = useSearchParams();
5383
5608
  const token = searchParams.get("token");
5384
- const [formData, setFormData] = useState19({ password: "", confirmPassword: "" });
5385
- const [loading, setLoading] = useState19(false);
5386
- const [message, setMessage] = useState19("");
5609
+ const [formData, setFormData] = useState20({ password: "", confirmPassword: "" });
5610
+ const [loading, setLoading] = useState20(false);
5611
+ const [message, setMessage] = useState20("");
5387
5612
  useEffect17(() => {
5388
5613
  if (!token) setMessage("Invalid reset link. Token is missing.");
5389
5614
  }, [token]);
@@ -5453,18 +5678,18 @@ function ResetPasswordPage() {
5453
5678
  }
5454
5679
 
5455
5680
  // src/admin/pages/InvitePage.tsx
5456
- import { useState as useState20, useEffect as useEffect18, Suspense as Suspense2 } from "react";
5681
+ import { useState as useState21, useEffect as useEffect18, Suspense as Suspense2 } from "react";
5457
5682
  import { useSearchParams as useSearchParams2 } from "next/navigation";
5458
5683
  import { jsx as jsx44, jsxs as jsxs35 } from "react/jsx-runtime";
5459
5684
  function InvitePageContent() {
5460
5685
  const searchParams = useSearchParams2();
5461
5686
  const token = searchParams.get("token");
5462
- const [formData, setFormData] = useState20({
5687
+ const [formData, setFormData] = useState21({
5463
5688
  password: "",
5464
5689
  confirmPassword: ""
5465
5690
  });
5466
- const [loading, setLoading] = useState20(false);
5467
- const [message, setMessage] = useState20("");
5691
+ const [loading, setLoading] = useState21(false);
5692
+ const [message, setMessage] = useState21("");
5468
5693
  useEffect18(() => {
5469
5694
  if (!token) {
5470
5695
  setMessage("Invalid invite link. Token is missing.");
@@ -5538,21 +5763,62 @@ function InvitePage() {
5538
5763
 
5539
5764
  // src/admin/pages/DashboardPage.tsx
5540
5765
  import { useSession as useSession4 } from "next-auth/react";
5541
- import { useEffect as useEffect19, useState as useState21 } from "react";
5542
- import { Users as Users4, Eye as Eye3, MousePointer, Globe, FileText, ClipboardList as ClipboardList2, UserCheck, TrendingUp, BarChart3, Activity } from "lucide-react";
5766
+ import { useContext as useContext3, useEffect as useEffect19, useMemo as useMemo3, useState as useState22 } from "react";
5767
+ import { useRouter as useRouter6 } from "next/navigation";
5768
+ import { Chart as ChartJS2, ArcElement, Tooltip as Tooltip2, Legend as Legend2 } from "chart.js";
5769
+ import { Doughnut } from "react-chartjs-2";
5770
+ import { Users as Users4, Eye as Eye2, MousePointer, Globe, FileText, ClipboardList as ClipboardList2, UserCheck, TrendingUp, BarChart3, Activity } from "lucide-react";
5543
5771
  import { Fragment as Fragment6, jsx as jsx45, jsxs as jsxs36 } from "react/jsx-runtime";
5772
+ ChartJS2.register(ArcElement, Tooltip2, Legend2);
5544
5773
  function DashboardPage() {
5545
5774
  const { data: session } = useSession4();
5546
- const [analyticsData, setAnalyticsData] = useState21(null);
5547
- const [dashboardStats, setDashboardStats] = useState21(null);
5548
- const [loading, setLoading] = useState21({ analytics: true, stats: true });
5549
- const [analyticsEnabled, setAnalyticsEnabled] = useState21(false);
5775
+ const router = useRouter6();
5776
+ const { storeEnabled } = useContext3(AdminConfigContext);
5777
+ const [analyticsData, setAnalyticsData] = useState22(null);
5778
+ const [ecommerceData, setEcommerceData] = useState22(null);
5779
+ const [dashboardStats, setDashboardStats] = useState22(null);
5780
+ const [loading, setLoading] = useState22({ analytics: true, stats: true, ecommerce: true });
5781
+ const [analyticsEnabled, setAnalyticsEnabled] = useState22(false);
5782
+ const [days, setDays] = useState22(30);
5783
+ const [activeTab, setActiveTab] = useState22("overview");
5784
+ const formatMoney4 = useMemo3(
5785
+ () => (value) => new Intl.NumberFormat(void 0, {
5786
+ style: "currency",
5787
+ currency: "INR",
5788
+ maximumFractionDigits: 0
5789
+ }).format(value || 0),
5790
+ []
5791
+ );
5792
+ const safePct = (v, max) => max > 0 ? Math.max(6, Math.round(v / max * 100)) : 0;
5793
+ const productPalette = ["#2563eb", "#0ea5e9", "#14b8a6", "#22c55e", "#eab308", "#f97316"];
5794
+ const salesBreakdownPalette = {
5795
+ sales: "#22c55e",
5796
+ returns: "#ef4444",
5797
+ replacements: "#f59e0b"
5798
+ };
5799
+ const contactTypeColor = (type) => {
5800
+ const t = type.trim().toLowerCase();
5801
+ if (t === "customer") return "#2563eb";
5802
+ if (t === "lead") return "#a855f7";
5803
+ if (t === "vendor") return "#14b8a6";
5804
+ return "#6b7280";
5805
+ };
5806
+ const metricBarColor = (label) => {
5807
+ const key = label.toLowerCase();
5808
+ if (key.includes("contact")) return "bg-blue-500";
5809
+ if (key.includes("submission")) return "bg-purple-500";
5810
+ if (key.includes("net sales")) return "bg-green-500";
5811
+ if (key.includes("gross sales")) return "bg-emerald-500";
5812
+ if (key.includes("return")) return "bg-red-500";
5813
+ return "bg-gray-600";
5814
+ };
5550
5815
  useEffect19(() => {
5551
5816
  const fetchData = async () => {
5552
- const analyticsPromise = fetch("/api/analytics?days=30");
5817
+ const analyticsPromise = fetch(`/api/analytics?days=${days}`);
5553
5818
  const statsPromise = fetch("/api/dashboard/stats");
5819
+ const ecommercePromise = storeEnabled ? fetch(`/api/dashboard/ecommerce?days=${days}`) : Promise.resolve(null);
5554
5820
  try {
5555
- const [analyticsResponse, statsResponse] = await Promise.all([analyticsPromise, statsPromise]);
5821
+ const [analyticsResponse, statsResponse, ecommerceResponse] = await Promise.all([analyticsPromise, statsPromise, ecommercePromise]);
5556
5822
  if (analyticsResponse.ok) {
5557
5823
  const data = await analyticsResponse.json();
5558
5824
  setAnalyticsData(data);
@@ -5570,15 +5836,22 @@ function DashboardPage() {
5570
5836
  const stats = await statsResponse.json();
5571
5837
  setDashboardStats(stats);
5572
5838
  }
5839
+ if (ecommerceResponse && ecommerceResponse.ok) {
5840
+ const ecommerce = await ecommerceResponse.json();
5841
+ setEcommerceData(ecommerce);
5842
+ } else {
5843
+ setEcommerceData(null);
5844
+ }
5573
5845
  } catch (error) {
5574
5846
  setAnalyticsEnabled(false);
5847
+ setEcommerceData(null);
5575
5848
  } finally {
5576
- setLoading({ analytics: false, stats: false });
5849
+ setLoading({ analytics: false, stats: false, ecommerce: false });
5577
5850
  }
5578
5851
  };
5579
5852
  fetchData();
5580
- }, []);
5581
- const isLoading = loading.analytics || loading.stats;
5853
+ }, [days, storeEnabled]);
5854
+ const isLoading = loading.analytics || loading.stats || storeEnabled && loading.ecommerce;
5582
5855
  return /* @__PURE__ */ jsxs36("div", { className: "min-w-0 rounded-lg bg-white shadow-md", children: [
5583
5856
  /* @__PURE__ */ jsx45("div", { className: "bg-gray-800 border-b border-gray-700 px-4 py-2.5 rounded-t-lg", children: /* @__PURE__ */ jsxs36("div", { className: "flex items-center justify-between", children: [
5584
5857
  /* @__PURE__ */ jsxs36("div", { children: [
@@ -5594,13 +5867,54 @@ function DashboardPage() {
5594
5867
  ] }) })
5595
5868
  ] }) }),
5596
5869
  /* @__PURE__ */ jsxs36("div", { className: "min-w-0 p-4 bg-gray-50", children: [
5597
- /* @__PURE__ */ jsxs36("div", { className: "mb-4", children: [
5598
- /* @__PURE__ */ jsxs36("div", { className: "flex items-center mb-2", children: [
5870
+ /* @__PURE__ */ jsxs36("div", { className: "flex flex-wrap items-center justify-between gap-2 mb-3", children: [
5871
+ /* @__PURE__ */ jsxs36("div", { className: "flex items-center gap-2", children: [
5872
+ /* @__PURE__ */ jsx45(
5873
+ "button",
5874
+ {
5875
+ onClick: () => setActiveTab("overview"),
5876
+ className: `text-xs px-2 py-1 rounded border ${activeTab === "overview" ? "bg-gray-800 text-white border-gray-800" : "bg-white text-gray-700 border-gray-300"}`,
5877
+ children: "Overview"
5878
+ }
5879
+ ),
5880
+ /* @__PURE__ */ jsx45(
5881
+ "button",
5882
+ {
5883
+ onClick: () => setActiveTab("crm"),
5884
+ className: `text-xs px-2 py-1 rounded border ${activeTab === "crm" ? "bg-gray-800 text-white border-gray-800" : "bg-white text-gray-700 border-gray-300"}`,
5885
+ children: "CRM / Engagement"
5886
+ }
5887
+ ),
5888
+ storeEnabled && /* @__PURE__ */ jsx45(
5889
+ "button",
5890
+ {
5891
+ onClick: () => setActiveTab("sales"),
5892
+ className: `text-xs px-2 py-1 rounded border ${activeTab === "sales" ? "bg-gray-800 text-white border-gray-800" : "bg-white text-gray-700 border-gray-300"}`,
5893
+ children: "Sales"
5894
+ }
5895
+ )
5896
+ ] }),
5897
+ /* @__PURE__ */ jsxs36(
5898
+ "select",
5899
+ {
5900
+ value: days,
5901
+ onChange: (e) => setDays(Number(e.target.value)),
5902
+ className: "border border-gray-300 text-xs rounded px-2 py-1 bg-white",
5903
+ children: [
5904
+ /* @__PURE__ */ jsx45("option", { value: 7, children: "Last 7 days" }),
5905
+ /* @__PURE__ */ jsx45("option", { value: 30, children: "Last 30 days" }),
5906
+ /* @__PURE__ */ jsx45("option", { value: 90, children: "Last 90 days" })
5907
+ ]
5908
+ }
5909
+ )
5910
+ ] }),
5911
+ activeTab === "overview" && /* @__PURE__ */ jsxs36("div", { className: "mb-5", children: [
5912
+ /* @__PURE__ */ jsxs36("div", { className: "flex items-center mb-3", children: [
5599
5913
  /* @__PURE__ */ jsx45(BarChart3, { className: "w-4 h-4 text-gray-600 mr-2" }),
5600
- /* @__PURE__ */ jsx45("h2", { className: "text-sm font-semibold text-gray-800", children: "Overview" })
5914
+ /* @__PURE__ */ jsx45("h2", { className: "text-sm font-semibold text-gray-800", children: "Contacts & Forms" })
5601
5915
  ] }),
5602
- /* @__PURE__ */ jsxs36("div", { className: "grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-3", children: [
5603
- /* @__PURE__ */ jsxs36("div", { className: "bg-white rounded border border-gray-200 p-2.5 shadow-sm", children: [
5916
+ /* @__PURE__ */ jsxs36("div", { className: "grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4", children: [
5917
+ /* @__PURE__ */ jsxs36("div", { className: "bg-white rounded border border-gray-200 p-3 shadow-sm", children: [
5604
5918
  /* @__PURE__ */ jsxs36("div", { className: "flex items-center justify-between mb-1.5", children: [
5605
5919
  /* @__PURE__ */ jsx45("p", { className: "text-xs font-medium text-gray-600", children: "Total Contacts" }),
5606
5920
  /* @__PURE__ */ jsx45("div", { className: "p-1 bg-gray-200 rounded", children: /* @__PURE__ */ jsx45(Users4, { className: "w-3.5 h-3.5 text-gray-600" }) })
@@ -5616,7 +5930,7 @@ function DashboardPage() {
5616
5930
  ] })
5617
5931
  ] })
5618
5932
  ] }),
5619
- /* @__PURE__ */ jsxs36("div", { className: "bg-white rounded border border-gray-200 p-2.5 shadow-sm", children: [
5933
+ /* @__PURE__ */ jsxs36("div", { className: "bg-white rounded border border-gray-200 p-3 shadow-sm", children: [
5620
5934
  /* @__PURE__ */ jsxs36("div", { className: "flex items-center justify-between mb-1.5", children: [
5621
5935
  /* @__PURE__ */ jsx45("p", { className: "text-xs font-medium text-gray-600", children: "Form Submissions" }),
5622
5936
  /* @__PURE__ */ jsx45("div", { className: "p-1 bg-gray-200 rounded", children: /* @__PURE__ */ jsx45(FileText, { className: "w-3.5 h-3.5 text-gray-600" }) })
@@ -5632,7 +5946,7 @@ function DashboardPage() {
5632
5946
  ] })
5633
5947
  ] })
5634
5948
  ] }),
5635
- /* @__PURE__ */ jsxs36("div", { className: "bg-white rounded border border-gray-200 p-2.5 shadow-sm", children: [
5949
+ /* @__PURE__ */ jsxs36("div", { className: "bg-white rounded border border-gray-200 p-3 shadow-sm", children: [
5636
5950
  /* @__PURE__ */ jsxs36("div", { className: "flex items-center justify-between mb-1.5", children: [
5637
5951
  /* @__PURE__ */ jsx45("p", { className: "text-xs font-medium text-gray-600", children: "Active Forms" }),
5638
5952
  /* @__PURE__ */ jsx45("div", { className: "p-1 bg-gray-200 rounded", children: /* @__PURE__ */ jsx45(ClipboardList2, { className: "w-3.5 h-3.5 text-gray-600" }) })
@@ -5642,7 +5956,7 @@ function DashboardPage() {
5642
5956
  /* @__PURE__ */ jsx45("p", { className: "text-xs text-gray-500", children: "Total" })
5643
5957
  ] })
5644
5958
  ] }),
5645
- /* @__PURE__ */ jsxs36("div", { className: "bg-white rounded border border-gray-200 p-2.5 shadow-sm", children: [
5959
+ /* @__PURE__ */ jsxs36("div", { className: "bg-white rounded border border-gray-200 p-3 shadow-sm", children: [
5646
5960
  /* @__PURE__ */ jsxs36("div", { className: "flex items-center justify-between mb-1.5", children: [
5647
5961
  /* @__PURE__ */ jsx45("p", { className: "text-xs font-medium text-gray-600", children: "Registered Users" }),
5648
5962
  /* @__PURE__ */ jsx45("div", { className: "p-1 bg-gray-200 rounded", children: /* @__PURE__ */ jsx45(UserCheck, { className: "w-3.5 h-3.5 text-gray-600" }) })
@@ -5654,8 +5968,151 @@ function DashboardPage() {
5654
5968
  ] })
5655
5969
  ] })
5656
5970
  ] }),
5657
- /* @__PURE__ */ jsx45("div", { className: "border-t-2 border-dotted border-gray-200 my-6" }),
5658
- analyticsEnabled && !isLoading && analyticsData && /* @__PURE__ */ jsxs36(Fragment6, { children: [
5971
+ activeTab === "overview" && !isLoading && /* @__PURE__ */ jsxs36("div", { className: "mb-6 bg-white rounded-lg border border-gray-200 p-4 shadow-sm", children: [
5972
+ /* @__PURE__ */ jsxs36("div", { className: "flex items-center mb-3", children: [
5973
+ /* @__PURE__ */ jsx45(Activity, { className: "w-4 h-4 text-gray-600 mr-2" }),
5974
+ /* @__PURE__ */ jsx45("h3", { className: "text-sm font-semibold text-gray-800", children: "Overview Snapshot" })
5975
+ ] }),
5976
+ /* @__PURE__ */ jsxs36("div", { className: "grid grid-cols-1 lg:grid-cols-2 gap-6", children: [
5977
+ /* @__PURE__ */ jsxs36("div", { children: [
5978
+ /* @__PURE__ */ jsx45("h4", { className: "text-xs font-semibold text-gray-700 mb-2", children: "Contacts & Forms" }),
5979
+ (() => {
5980
+ const rows = [
5981
+ { label: "Contacts (total)", value: dashboardStats?.contacts.total || 0 },
5982
+ { label: "New contacts", value: dashboardStats?.contacts.recent || 0 },
5983
+ { label: "Submissions", value: dashboardStats?.forms.submissions || 0 },
5984
+ { label: "New submissions", value: dashboardStats?.forms.recentSubmissions || 0 }
5985
+ ];
5986
+ const max = Math.max(...rows.map((r) => r.value), 0);
5987
+ return /* @__PURE__ */ jsx45("div", { className: "space-y-2", children: rows.map((r) => /* @__PURE__ */ jsxs36("div", { children: [
5988
+ /* @__PURE__ */ jsxs36("div", { className: "flex items-center justify-between text-xs mb-1", children: [
5989
+ /* @__PURE__ */ jsx45("span", { className: "text-gray-600", children: r.label }),
5990
+ /* @__PURE__ */ jsx45("span", { className: "font-semibold text-gray-900", children: r.value })
5991
+ ] }),
5992
+ /* @__PURE__ */ jsx45("div", { className: "h-2 rounded bg-gray-100 overflow-hidden", children: /* @__PURE__ */ jsx45("div", { className: `h-2 rounded ${metricBarColor(r.label)}`, style: { width: `${safePct(r.value, max)}%` } }) })
5993
+ ] }, r.label)) });
5994
+ })()
5995
+ ] }),
5996
+ storeEnabled && ecommerceData && /* @__PURE__ */ jsxs36("div", { children: [
5997
+ /* @__PURE__ */ jsx45("h4", { className: "text-xs font-semibold text-gray-700 mb-2", children: "Sales, Returns & Products" }),
5998
+ (() => {
5999
+ const salesBase = Math.max(ecommerceData.kpis.grossSales, 1);
6000
+ const rows = [
6001
+ { label: "Net sales", value: ecommerceData.kpis.netSales, display: formatMoney4(ecommerceData.kpis.netSales) },
6002
+ { label: "Gross sales", value: ecommerceData.kpis.grossSales, display: formatMoney4(ecommerceData.kpis.grossSales) },
6003
+ { label: "Return value", value: ecommerceData.kpis.returnValue, display: formatMoney4(ecommerceData.kpis.returnValue) },
6004
+ { label: "Return rate", value: ecommerceData.kpis.returnRate, display: `${ecommerceData.kpis.returnRate.toFixed(1)}%` }
6005
+ ];
6006
+ const topProduct = ecommerceData.topProducts[0];
6007
+ return /* @__PURE__ */ jsxs36("div", { className: "space-y-2", children: [
6008
+ rows.map((r) => /* @__PURE__ */ jsxs36("div", { children: [
6009
+ /* @__PURE__ */ jsxs36("div", { className: "flex items-center justify-between text-xs mb-1", children: [
6010
+ /* @__PURE__ */ jsx45("span", { className: "text-gray-600", children: r.label }),
6011
+ /* @__PURE__ */ jsx45("span", { className: "font-semibold text-gray-900", children: r.display })
6012
+ ] }),
6013
+ /* @__PURE__ */ jsx45("div", { className: "h-2 rounded bg-gray-100 overflow-hidden", children: /* @__PURE__ */ jsx45(
6014
+ "div",
6015
+ {
6016
+ className: `h-2 rounded ${metricBarColor(r.label)}`,
6017
+ style: { width: `${r.label === "Return rate" ? Math.max(6, Math.round(r.value)) : safePct(r.value, salesBase)}%` }
6018
+ }
6019
+ ) })
6020
+ ] }, r.label)),
6021
+ topProduct && /* @__PURE__ */ jsxs36("div", { className: "pt-1 text-xs text-gray-600", children: [
6022
+ "Top product: ",
6023
+ /* @__PURE__ */ jsx45("span", { className: "font-medium text-gray-900", children: topProduct.name }),
6024
+ " (",
6025
+ topProduct.units,
6026
+ " units)"
6027
+ ] })
6028
+ ] });
6029
+ })()
6030
+ ] })
6031
+ ] })
6032
+ ] }),
6033
+ activeTab === "overview" && !isLoading && /* @__PURE__ */ jsxs36("div", { className: "grid grid-cols-1 lg:grid-cols-3 gap-6 mb-7", children: [
6034
+ storeEnabled && ecommerceData && /* @__PURE__ */ jsxs36("div", { className: "bg-white rounded-lg border border-gray-200 p-4 shadow-sm", children: [
6035
+ /* @__PURE__ */ jsx45("h3", { className: "text-sm font-semibold text-gray-800 mb-3", children: "Sales vs Returns vs Replacements" }),
6036
+ /* @__PURE__ */ jsx45("div", { className: "h-56", children: /* @__PURE__ */ jsx45(
6037
+ Doughnut,
6038
+ {
6039
+ data: {
6040
+ labels: ["Sales", "Returns", "Replacements"],
6041
+ datasets: [
6042
+ {
6043
+ data: [
6044
+ ecommerceData.salesBreakdown?.sales.value ?? ecommerceData.kpis.grossSales,
6045
+ ecommerceData.salesBreakdown?.returns.value ?? ecommerceData.kpis.returnValue,
6046
+ ecommerceData.salesBreakdown?.replacements.value ?? 0
6047
+ ],
6048
+ backgroundColor: [
6049
+ salesBreakdownPalette.sales,
6050
+ salesBreakdownPalette.returns,
6051
+ salesBreakdownPalette.replacements
6052
+ ],
6053
+ borderWidth: 0
6054
+ }
6055
+ ]
6056
+ },
6057
+ options: {
6058
+ maintainAspectRatio: false,
6059
+ plugins: {
6060
+ legend: { position: "bottom" }
6061
+ }
6062
+ }
6063
+ }
6064
+ ) })
6065
+ ] }),
6066
+ storeEnabled && ecommerceData && /* @__PURE__ */ jsxs36("div", { className: "bg-white rounded-lg border border-gray-200 p-4 shadow-sm", children: [
6067
+ /* @__PURE__ */ jsx45("h3", { className: "text-sm font-semibold text-gray-800 mb-3", children: "Product-wise Sales (Top)" }),
6068
+ /* @__PURE__ */ jsx45("div", { className: "h-56", children: /* @__PURE__ */ jsx45(
6069
+ Doughnut,
6070
+ {
6071
+ data: {
6072
+ labels: ecommerceData.topProducts.map((p) => p.name),
6073
+ datasets: [
6074
+ {
6075
+ data: ecommerceData.topProducts.map((p) => p.sales),
6076
+ backgroundColor: productPalette.slice(0, Math.max(3, ecommerceData.topProducts.length)),
6077
+ borderWidth: 0
6078
+ }
6079
+ ]
6080
+ },
6081
+ options: {
6082
+ maintainAspectRatio: false,
6083
+ plugins: {
6084
+ legend: { position: "bottom" }
6085
+ }
6086
+ }
6087
+ }
6088
+ ) })
6089
+ ] }),
6090
+ /* @__PURE__ */ jsxs36("div", { className: "bg-white rounded-lg border border-gray-200 p-4 shadow-sm", children: [
6091
+ /* @__PURE__ */ jsx45("h3", { className: "text-sm font-semibold text-gray-800 mb-3", children: "Contact Distribution" }),
6092
+ /* @__PURE__ */ jsx45("div", { className: "h-56", children: /* @__PURE__ */ jsx45(
6093
+ Doughnut,
6094
+ {
6095
+ data: {
6096
+ labels: (dashboardStats?.contactTypes?.length ? dashboardStats.contactTypes : [{ type: "unknown", count: dashboardStats?.contacts.total || 0 }]).map((c) => c.type),
6097
+ datasets: [
6098
+ {
6099
+ data: (dashboardStats?.contactTypes?.length ? dashboardStats.contactTypes : [{ type: "unknown", count: dashboardStats?.contacts.total || 0 }]).map((c) => c.count),
6100
+ backgroundColor: (dashboardStats?.contactTypes?.length ? dashboardStats.contactTypes : [{ type: "unknown", count: dashboardStats?.contacts.total || 0 }]).map((c) => contactTypeColor(c.type)),
6101
+ borderWidth: 0
6102
+ }
6103
+ ]
6104
+ },
6105
+ options: {
6106
+ maintainAspectRatio: false,
6107
+ plugins: {
6108
+ legend: { position: "bottom" }
6109
+ }
6110
+ }
6111
+ }
6112
+ ) })
6113
+ ] })
6114
+ ] }),
6115
+ activeTab === "overview" && analyticsEnabled && !isLoading && analyticsData && /* @__PURE__ */ jsxs36(Fragment6, { children: [
5659
6116
  /* @__PURE__ */ jsxs36("div", { className: "mb-4", children: [
5660
6117
  /* @__PURE__ */ jsxs36("div", { className: "flex items-center mb-2", children: [
5661
6118
  /* @__PURE__ */ jsx45(Globe, { className: "w-4 h-4 text-gray-600 mr-2" }),
@@ -5678,7 +6135,7 @@ function DashboardPage() {
5678
6135
  title: "Page Views",
5679
6136
  value: analyticsData.pageViews.toLocaleString(),
5680
6137
  subtitle: "Last 30 days",
5681
- icon: /* @__PURE__ */ jsx45(Eye3, { className: "w-5 h-5" }),
6138
+ icon: /* @__PURE__ */ jsx45(Eye2, { className: "w-5 h-5" }),
5682
6139
  trend: { value: 8.2, isPositive: true }
5683
6140
  }
5684
6141
  ),
@@ -5741,33 +6198,281 @@ function DashboardPage() {
5741
6198
  /* @__PURE__ */ jsx45("div", { className: "border-t-2 border-dotted border-gray-200 my-6" }),
5742
6199
  /* @__PURE__ */ jsx45("div", { className: "mb-6", children: /* @__PURE__ */ jsx45(GeographicMap, { data: analyticsData.geographicData }) })
5743
6200
  ] }),
6201
+ activeTab === "crm" && !isLoading && /* @__PURE__ */ jsxs36(Fragment6, { children: [
6202
+ /* @__PURE__ */ jsxs36("div", { className: "mb-4", children: [
6203
+ /* @__PURE__ */ jsxs36("div", { className: "flex items-center mb-2", children: [
6204
+ /* @__PURE__ */ jsx45(Users4, { className: "w-4 h-4 text-gray-600 mr-2" }),
6205
+ /* @__PURE__ */ jsx45("h2", { className: "text-sm font-semibold text-gray-800", children: "CRM Activity" })
6206
+ ] }),
6207
+ /* @__PURE__ */ jsxs36("div", { className: "grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-3", children: [
6208
+ /* @__PURE__ */ jsxs36("button", { onClick: () => router.push("/admin/contacts"), className: "text-left bg-white rounded border border-gray-200 p-2.5 shadow-sm", children: [
6209
+ /* @__PURE__ */ jsx45("p", { className: "text-xs text-gray-600", children: "Contacts" }),
6210
+ /* @__PURE__ */ jsx45("p", { className: "text-lg font-bold text-gray-900", children: dashboardStats?.contacts.total || 0 }),
6211
+ /* @__PURE__ */ jsxs36("p", { className: "text-xs text-green-600", children: [
6212
+ "+",
6213
+ dashboardStats?.contacts.recent || 0,
6214
+ " recent"
6215
+ ] })
6216
+ ] }),
6217
+ /* @__PURE__ */ jsxs36("button", { onClick: () => router.push("/admin/forms"), className: "text-left bg-white rounded border border-gray-200 p-2.5 shadow-sm", children: [
6218
+ /* @__PURE__ */ jsx45("p", { className: "text-xs text-gray-600", children: "Active Forms" }),
6219
+ /* @__PURE__ */ jsx45("p", { className: "text-lg font-bold text-gray-900", children: dashboardStats?.forms.total || 0 })
6220
+ ] }),
6221
+ /* @__PURE__ */ jsxs36("button", { onClick: () => router.push("/admin/submissions"), className: "text-left bg-white rounded border border-gray-200 p-2.5 shadow-sm", children: [
6222
+ /* @__PURE__ */ jsx45("p", { className: "text-xs text-gray-600", children: "Form Submissions" }),
6223
+ /* @__PURE__ */ jsx45("p", { className: "text-lg font-bold text-gray-900", children: dashboardStats?.forms.submissions || 0 }),
6224
+ /* @__PURE__ */ jsxs36("p", { className: "text-xs text-green-600", children: [
6225
+ "+",
6226
+ dashboardStats?.forms.recentSubmissions || 0,
6227
+ " recent"
6228
+ ] })
6229
+ ] }),
6230
+ /* @__PURE__ */ jsxs36("button", { onClick: () => router.push("/admin/blogs"), className: "text-left bg-white rounded border border-gray-200 p-2.5 shadow-sm", children: [
6231
+ /* @__PURE__ */ jsx45("p", { className: "text-xs text-gray-600", children: "Blogs" }),
6232
+ /* @__PURE__ */ jsx45("p", { className: "text-lg font-bold text-gray-900", children: dashboardStats?.blogs || 0 })
6233
+ ] })
6234
+ ] })
6235
+ ] }),
6236
+ /* @__PURE__ */ jsxs36("div", { className: "grid grid-cols-1 lg:grid-cols-2 gap-6 mb-6", children: [
6237
+ /* @__PURE__ */ jsxs36("div", { className: "bg-white rounded-lg border border-gray-100 p-4 shadow-sm", children: [
6238
+ /* @__PURE__ */ jsx45("h3", { className: "text-base font-semibold text-gray-800 mb-3", children: "Engagement Funnel" }),
6239
+ (() => {
6240
+ const contacts = dashboardStats?.contacts.total || 0;
6241
+ const submissions = dashboardStats?.forms.submissions || 0;
6242
+ const visitors = analyticsData?.visitors || 0;
6243
+ const base = Math.max(visitors, contacts, submissions, 1);
6244
+ const rows = [
6245
+ { label: "Visitors", value: visitors },
6246
+ { label: "Contacts", value: contacts },
6247
+ { label: "Submissions", value: submissions }
6248
+ ];
6249
+ return /* @__PURE__ */ jsxs36("div", { className: "space-y-3", children: [
6250
+ rows.map((r) => /* @__PURE__ */ jsxs36("div", { children: [
6251
+ /* @__PURE__ */ jsxs36("div", { className: "flex items-center justify-between text-xs mb-1", children: [
6252
+ /* @__PURE__ */ jsx45("span", { className: "text-gray-600", children: r.label }),
6253
+ /* @__PURE__ */ jsx45("span", { className: "font-semibold text-gray-900", children: r.value.toLocaleString() })
6254
+ ] }),
6255
+ /* @__PURE__ */ jsx45("div", { className: "h-2 rounded bg-gray-100 overflow-hidden", children: /* @__PURE__ */ jsx45("div", { className: "h-2 bg-gray-700 rounded", style: { width: `${safePct(r.value, base)}%` } }) })
6256
+ ] }, r.label)),
6257
+ /* @__PURE__ */ jsxs36("div", { className: "pt-1 text-xs text-gray-600", children: [
6258
+ "Contact rate:",
6259
+ " ",
6260
+ /* @__PURE__ */ jsxs36("span", { className: "font-semibold text-gray-900", children: [
6261
+ visitors > 0 ? (contacts / visitors * 100).toFixed(1) : "0.0",
6262
+ "%"
6263
+ ] }),
6264
+ " ",
6265
+ " | Submission rate:",
6266
+ " ",
6267
+ /* @__PURE__ */ jsxs36("span", { className: "font-semibold text-gray-900", children: [
6268
+ visitors > 0 ? (submissions / visitors * 100).toFixed(1) : "0.0",
6269
+ "%"
6270
+ ] })
6271
+ ] })
6272
+ ] });
6273
+ })()
6274
+ ] }),
6275
+ /* @__PURE__ */ jsxs36("div", { className: "bg-white rounded-lg border border-gray-100 p-4 shadow-sm", children: [
6276
+ /* @__PURE__ */ jsx45("h3", { className: "text-base font-semibold text-gray-800 mb-3", children: "CRM Distribution" }),
6277
+ (() => {
6278
+ const contacts = dashboardStats?.contacts.total || 0;
6279
+ const forms = dashboardStats?.forms.total || 0;
6280
+ const blogs = dashboardStats?.blogs || 0;
6281
+ const users = dashboardStats?.users || 0;
6282
+ const base = Math.max(contacts, forms, blogs, users, 1);
6283
+ const rows = [
6284
+ { label: "Contacts", value: contacts },
6285
+ { label: "Forms", value: forms },
6286
+ { label: "Blogs", value: blogs },
6287
+ { label: "Users", value: users }
6288
+ ];
6289
+ return /* @__PURE__ */ jsx45("div", { className: "space-y-2", children: rows.map((r) => /* @__PURE__ */ jsxs36("div", { children: [
6290
+ /* @__PURE__ */ jsxs36("div", { className: "flex items-center justify-between text-xs mb-1", children: [
6291
+ /* @__PURE__ */ jsx45("span", { className: "text-gray-600", children: r.label }),
6292
+ /* @__PURE__ */ jsx45("span", { className: "font-semibold text-gray-900", children: r.value })
6293
+ ] }),
6294
+ /* @__PURE__ */ jsx45("div", { className: "h-2 rounded bg-gray-100 overflow-hidden", children: /* @__PURE__ */ jsx45("div", { className: "h-2 bg-gray-700 rounded", style: { width: `${safePct(r.value, base)}%` } }) })
6295
+ ] }, r.label)) });
6296
+ })()
6297
+ ] })
6298
+ ] }),
6299
+ analyticsEnabled && analyticsData && /* @__PURE__ */ jsxs36("div", { className: "bg-white rounded-lg border border-gray-100 p-4 shadow-sm mb-2", children: [
6300
+ /* @__PURE__ */ jsx45("h3", { className: "text-base font-semibold text-gray-800 mb-3", children: "Top Content & Sources" }),
6301
+ /* @__PURE__ */ jsxs36("div", { className: "grid grid-cols-1 lg:grid-cols-2 gap-6", children: [
6302
+ /* @__PURE__ */ jsxs36("div", { children: [
6303
+ /* @__PURE__ */ jsx45("p", { className: "text-xs font-semibold text-gray-700 mb-2", children: "Top Pages" }),
6304
+ /* @__PURE__ */ jsx45("div", { className: "space-y-1", children: analyticsData.topPages.slice(0, 5).map((page, index) => /* @__PURE__ */ jsxs36("div", { className: "flex items-center justify-between text-xs", children: [
6305
+ /* @__PURE__ */ jsx45("span", { className: "text-gray-600 truncate max-w-[75%]", children: page.page }),
6306
+ /* @__PURE__ */ jsx45("span", { className: "font-semibold text-gray-900", children: page.views.toLocaleString() })
6307
+ ] }, index)) })
6308
+ ] }),
6309
+ /* @__PURE__ */ jsxs36("div", { children: [
6310
+ /* @__PURE__ */ jsx45("p", { className: "text-xs font-semibold text-gray-700 mb-2", children: "Traffic Sources" }),
6311
+ /* @__PURE__ */ jsx45("div", { className: "space-y-1", children: analyticsData.trafficSources.slice(0, 5).map((source, index) => /* @__PURE__ */ jsxs36("div", { className: "flex items-center justify-between text-xs", children: [
6312
+ /* @__PURE__ */ jsx45("span", { className: "text-gray-600", children: source.source }),
6313
+ /* @__PURE__ */ jsx45("span", { className: "font-semibold text-gray-900", children: source.sessions.toLocaleString() })
6314
+ ] }, index)) })
6315
+ ] })
6316
+ ] })
6317
+ ] })
6318
+ ] }),
6319
+ activeTab === "sales" && !isLoading && storeEnabled && ecommerceData && /* @__PURE__ */ jsxs36(Fragment6, { children: [
6320
+ /* @__PURE__ */ jsx45("div", { className: "border-t-2 border-dotted border-gray-200 my-6" }),
6321
+ /* @__PURE__ */ jsxs36("div", { className: "mb-4", children: [
6322
+ /* @__PURE__ */ jsxs36("div", { className: "flex items-center mb-2", children: [
6323
+ /* @__PURE__ */ jsx45(BarChart3, { className: "w-4 h-4 text-gray-600 mr-2" }),
6324
+ /* @__PURE__ */ jsx45("h2", { className: "text-sm font-semibold text-gray-800", children: "Store Analytics" })
6325
+ ] }),
6326
+ /* @__PURE__ */ jsxs36("div", { className: "grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-3", children: [
6327
+ /* @__PURE__ */ jsxs36("button", { onClick: () => router.push("/admin/orders"), className: "text-left bg-white rounded border border-gray-200 p-2.5 shadow-sm", children: [
6328
+ /* @__PURE__ */ jsx45("p", { className: "text-xs text-gray-600", children: "Net Sales" }),
6329
+ /* @__PURE__ */ jsx45("p", { className: "text-lg font-bold text-gray-900", children: formatMoney4(ecommerceData.kpis.netSales) })
6330
+ ] }),
6331
+ /* @__PURE__ */ jsxs36("button", { onClick: () => router.push("/admin/orders"), className: "text-left bg-white rounded border border-gray-200 p-2.5 shadow-sm", children: [
6332
+ /* @__PURE__ */ jsx45("p", { className: "text-xs text-gray-600", children: "Orders" }),
6333
+ /* @__PURE__ */ jsx45("p", { className: "text-lg font-bold text-gray-900", children: ecommerceData.kpis.ordersPlaced })
6334
+ ] }),
6335
+ /* @__PURE__ */ jsxs36("button", { onClick: () => router.push("/admin/orders"), className: "text-left bg-white rounded border border-gray-200 p-2.5 shadow-sm", children: [
6336
+ /* @__PURE__ */ jsx45("p", { className: "text-xs text-gray-600", children: "AOV" }),
6337
+ /* @__PURE__ */ jsx45("p", { className: "text-lg font-bold text-gray-900", children: formatMoney4(ecommerceData.kpis.averageOrderValue) })
6338
+ ] }),
6339
+ /* @__PURE__ */ jsxs36("button", { onClick: () => router.push("/admin/contacts"), className: "text-left bg-white rounded border border-gray-200 p-2.5 shadow-sm", children: [
6340
+ /* @__PURE__ */ jsx45("p", { className: "text-xs text-gray-600", children: "Returning Customer Rate" }),
6341
+ /* @__PURE__ */ jsxs36("p", { className: "text-lg font-bold text-gray-900", children: [
6342
+ ecommerceData.kpis.returningCustomerRate.toFixed(1),
6343
+ "%"
6344
+ ] })
6345
+ ] }),
6346
+ /* @__PURE__ */ jsxs36("button", { onClick: () => router.push("/admin/orders"), className: "text-left bg-white rounded border border-gray-200 p-2.5 shadow-sm", children: [
6347
+ /* @__PURE__ */ jsx45("p", { className: "text-xs text-gray-600", children: "Return Rate" }),
6348
+ /* @__PURE__ */ jsxs36("p", { className: "text-lg font-bold text-gray-900", children: [
6349
+ ecommerceData.kpis.returnRate.toFixed(1),
6350
+ "%"
6351
+ ] })
6352
+ ] }),
6353
+ /* @__PURE__ */ jsxs36("button", { onClick: () => router.push("/admin/payments"), className: "text-left bg-white rounded border border-gray-200 p-2.5 shadow-sm", children: [
6354
+ /* @__PURE__ */ jsx45("p", { className: "text-xs text-gray-600", children: "Payment Success" }),
6355
+ /* @__PURE__ */ jsxs36("p", { className: "text-lg font-bold text-gray-900", children: [
6356
+ ecommerceData.kpis.paymentSuccessRate.toFixed(1),
6357
+ "%"
6358
+ ] })
6359
+ ] })
6360
+ ] })
6361
+ ] }),
6362
+ /* @__PURE__ */ jsxs36("div", { className: "grid grid-cols-1 lg:grid-cols-2 gap-6 mb-6", children: [
6363
+ /* @__PURE__ */ jsxs36("div", { className: "bg-white rounded-lg border border-gray-100 p-4 shadow-sm", children: [
6364
+ /* @__PURE__ */ jsx45("h3", { className: "text-base font-semibold text-gray-800 mb-3", children: "Sales Over Time" }),
6365
+ /* @__PURE__ */ jsx45("div", { className: "space-y-2 max-h-64 overflow-auto", children: ecommerceData.salesOverTime.slice(-10).map((point) => /* @__PURE__ */ jsxs36("div", { className: "flex items-center justify-between text-xs", children: [
6366
+ /* @__PURE__ */ jsx45("span", { className: "text-gray-600", children: point.date }),
6367
+ /* @__PURE__ */ jsxs36("span", { className: "font-semibold text-gray-900", children: [
6368
+ formatMoney4(point.value),
6369
+ " (",
6370
+ point.orders,
6371
+ ")"
6372
+ ] })
6373
+ ] }, point.date)) })
6374
+ ] }),
6375
+ /* @__PURE__ */ jsxs36("div", { className: "bg-white rounded-lg border border-gray-100 p-4 shadow-sm", children: [
6376
+ /* @__PURE__ */ jsx45("h3", { className: "text-base font-semibold text-gray-800 mb-3", children: "Top Products" }),
6377
+ /* @__PURE__ */ jsx45("div", { className: "space-y-2", children: ecommerceData.topProducts.map((p, idx) => /* @__PURE__ */ jsxs36(
6378
+ "button",
6379
+ {
6380
+ onClick: () => router.push("/admin/products"),
6381
+ className: "w-full text-left flex items-center justify-between p-2 bg-gray-50 rounded-lg",
6382
+ children: [
6383
+ /* @__PURE__ */ jsx45("span", { className: "text-xs text-gray-700 truncate max-w-[70%]", children: p.name }),
6384
+ /* @__PURE__ */ jsxs36("span", { className: "text-xs font-semibold text-gray-900", children: [
6385
+ p.units,
6386
+ " / ",
6387
+ formatMoney4(p.sales)
6388
+ ] })
6389
+ ]
6390
+ },
6391
+ `${p.name}-${idx}`
6392
+ )) })
6393
+ ] })
6394
+ ] }),
6395
+ /* @__PURE__ */ jsxs36("div", { className: "grid grid-cols-1 lg:grid-cols-3 gap-6 mb-2", children: [
6396
+ /* @__PURE__ */ jsxs36("div", { className: "bg-white rounded-lg border border-gray-100 p-4 shadow-sm", children: [
6397
+ /* @__PURE__ */ jsx45("h3", { className: "text-base font-semibold text-gray-800 mb-2", children: "Customer Mix" }),
6398
+ /* @__PURE__ */ jsxs36("p", { className: "text-xs text-gray-700", children: [
6399
+ "New: ",
6400
+ ecommerceData.customerMix.newCustomers
6401
+ ] }),
6402
+ /* @__PURE__ */ jsxs36("p", { className: "text-xs text-gray-700", children: [
6403
+ "Returning: ",
6404
+ ecommerceData.customerMix.returningCustomers
6405
+ ] }),
6406
+ /* @__PURE__ */ jsxs36("p", { className: "text-xs text-gray-700", children: [
6407
+ "Repeat rate: ",
6408
+ ecommerceData.customerMix.repeatPurchaseRate.toFixed(1),
6409
+ "%"
6410
+ ] })
6411
+ ] }),
6412
+ /* @__PURE__ */ jsxs36("div", { className: "bg-white rounded-lg border border-gray-100 p-4 shadow-sm", children: [
6413
+ /* @__PURE__ */ jsx45("h3", { className: "text-base font-semibold text-gray-800 mb-2", children: "Returns Trend" }),
6414
+ /* @__PURE__ */ jsxs36("p", { className: "text-xs text-gray-700", children: [
6415
+ "Return value: ",
6416
+ formatMoney4(ecommerceData.kpis.returnValue)
6417
+ ] }),
6418
+ /* @__PURE__ */ jsxs36("p", { className: "text-xs text-gray-700", children: [
6419
+ "Return orders: ",
6420
+ ecommerceData.returnsTrend.reduce((s, r) => s + r.count, 0)
6421
+ ] }),
6422
+ /* @__PURE__ */ jsxs36("p", { className: "text-xs text-gray-700", children: [
6423
+ "Return rate: ",
6424
+ ecommerceData.kpis.returnRate.toFixed(1),
6425
+ "%"
6426
+ ] })
6427
+ ] }),
6428
+ /* @__PURE__ */ jsxs36("div", { className: "bg-white rounded-lg border border-gray-100 p-4 shadow-sm", children: [
6429
+ /* @__PURE__ */ jsx45("h3", { className: "text-base font-semibold text-gray-800 mb-2", children: "Inventory Risk" }),
6430
+ /* @__PURE__ */ jsxs36("p", { className: "text-xs text-gray-700", children: [
6431
+ "Out of stock: ",
6432
+ ecommerceData.inventoryRisk.outOfStockCount
6433
+ ] }),
6434
+ /* @__PURE__ */ jsxs36("p", { className: "text-xs text-gray-700", children: [
6435
+ "Low stock: ",
6436
+ ecommerceData.inventoryRisk.lowStockCount
6437
+ ] }),
6438
+ /* @__PURE__ */ jsxs36("p", { className: "text-xs text-gray-700", children: [
6439
+ "Total units: ",
6440
+ ecommerceData.inventoryRisk.totalInventory
6441
+ ] })
6442
+ ] })
6443
+ ] })
6444
+ ] }),
5744
6445
  isLoading && /* @__PURE__ */ jsxs36("div", { className: "flex items-center justify-center py-8", children: [
5745
6446
  /* @__PURE__ */ jsx45("div", { className: "animate-spin rounded-full h-5 w-5 border-2 border-gray-300 border-t-gray-600" }),
5746
6447
  /* @__PURE__ */ jsx45("span", { className: "ml-2 text-sm text-gray-600", children: "Loading dashboard data..." })
5747
6448
  ] }),
5748
- !isLoading && !analyticsEnabled && /* @__PURE__ */ jsxs36("div", { className: "text-center py-8", children: [
6449
+ !isLoading && activeTab === "overview" && !analyticsEnabled && /* @__PURE__ */ jsxs36("div", { className: "text-center py-8", children: [
5749
6450
  /* @__PURE__ */ jsx45(Globe, { className: "w-10 h-10 text-gray-400 mx-auto mb-3" }),
5750
6451
  /* @__PURE__ */ jsx45("h3", { className: "text-base font-medium text-gray-600 mb-1", children: "Analytics Not Configured" }),
5751
6452
  /* @__PURE__ */ jsx45("p", { className: "text-xs text-gray-500", children: "Google Analytics integration is required to view website analytics." })
6453
+ ] }),
6454
+ !isLoading && activeTab === "sales" && !storeEnabled && /* @__PURE__ */ jsxs36("div", { className: "text-center py-8", children: [
6455
+ /* @__PURE__ */ jsx45("h3", { className: "text-base font-medium text-gray-600 mb-1", children: "Store analytics unavailable" }),
6456
+ /* @__PURE__ */ jsx45("p", { className: "text-xs text-gray-500", children: "Enable store/ecomm to view sales reports." })
5752
6457
  ] })
5753
6458
  ] })
5754
6459
  ] });
5755
6460
  }
5756
6461
 
5757
6462
  // src/admin/pages/AdminPageResolver.tsx
5758
- import { useState as useState35, useEffect as useEffect33, useContext as useContext6, useMemo as useMemo2 } from "react";
5759
- import { useRouter as useRouter13 } from "next/navigation";
6463
+ import { useState as useState36, useEffect as useEffect33, useContext as useContext7, useMemo as useMemo4 } from "react";
6464
+ import { useRouter as useRouter15 } from "next/navigation";
5760
6465
 
5761
6466
  // src/admin/pages/SubmissionDetailPage.tsx
5762
- import { useEffect as useEffect20, useState as useState22 } from "react";
6467
+ import { useEffect as useEffect20, useState as useState23 } from "react";
5763
6468
  import Link9 from "next/link";
5764
6469
  import { ArrowLeft as ArrowLeft5 } from "lucide-react";
5765
6470
 
5766
6471
  // src/components/Admin/DetailPageHeader.tsx
5767
6472
  import Link8 from "next/link";
5768
- import { useRouter as useRouter5 } from "next/navigation";
5769
- import { ArrowLeft as ArrowLeft4, MoreVertical as MoreVertical2, X as X13 } from "lucide-react";
5770
- import { jsx as jsx46, jsxs as jsxs37 } from "react/jsx-runtime";
6473
+ import { useRouter as useRouter7 } from "next/navigation";
6474
+ import { ArrowLeft as ArrowLeft4, X as X13 } from "lucide-react";
6475
+ import { Fragment as Fragment7, jsx as jsx46, jsxs as jsxs37 } from "react/jsx-runtime";
5771
6476
  function DetailPageHeader({
5772
6477
  title,
5773
6478
  subtitle,
@@ -5777,7 +6482,7 @@ function DetailPageHeader({
5777
6482
  onClose,
5778
6483
  menuItems = []
5779
6484
  }) {
5780
- const router = useRouter5();
6485
+ const router = useRouter7();
5781
6486
  const handleClose = () => {
5782
6487
  if (onClose) onClose();
5783
6488
  else if (closeHref) router.push(closeHref);
@@ -5802,20 +6507,32 @@ function DetailPageHeader({
5802
6507
  ] })
5803
6508
  ] }),
5804
6509
  /* @__PURE__ */ jsxs37("div", { className: "flex items-center gap-2 shrink-0", children: [
5805
- menuItems.length > 0 && /* @__PURE__ */ jsxs37(DropdownMenu, { children: [
5806
- /* @__PURE__ */ jsx46(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsxs37(
5807
- Button,
5808
- {
5809
- variant: "ghost",
5810
- size: "icon",
5811
- className: "h-8 w-8 text-gray-300 hover:text-white hover:bg-gray-700",
5812
- children: [
5813
- /* @__PURE__ */ jsx46(MoreVertical2, { className: "h-4 w-4" }),
5814
- /* @__PURE__ */ jsx46("span", { className: "sr-only", children: "More" })
5815
- ]
5816
- }
5817
- ) }),
5818
- /* @__PURE__ */ jsx46(DropdownMenuContent, { align: "end", className: "w-48", children: menuItems.map((item, i) => /* @__PURE__ */ jsx46(DropdownMenuItem, { onClick: item.onClick, children: item.label }, i)) })
6510
+ menuItems.length > 0 && /* @__PURE__ */ jsxs37(Fragment7, { children: [
6511
+ /* @__PURE__ */ jsx46("div", { className: "flex items-center gap-2 md:hidden", children: menuItems.map((item, i) => {
6512
+ const Icon2 = item.icon;
6513
+ return /* @__PURE__ */ jsxs37(
6514
+ Button,
6515
+ {
6516
+ variant: item.variant ?? "outline",
6517
+ size: "icon",
6518
+ className: "h-8 w-8 border border-gray-600 bg-transparent text-white hover:bg-gray-700",
6519
+ onClick: item.onClick,
6520
+ title: item.label,
6521
+ children: [
6522
+ /* @__PURE__ */ jsx46(Icon2, { className: "h-4 w-4" }),
6523
+ /* @__PURE__ */ jsx46("span", { className: "sr-only", children: item.label })
6524
+ ]
6525
+ },
6526
+ i
6527
+ );
6528
+ }) }),
6529
+ /* @__PURE__ */ jsx46("div", { className: "hidden md:flex items-center gap-2", children: menuItems.map((item, i) => {
6530
+ const Icon2 = item.icon;
6531
+ return /* @__PURE__ */ jsxs37(Button, { variant: item.variant ?? "outline", size: "sm", onClick: item.onClick, children: [
6532
+ /* @__PURE__ */ jsx46(Icon2, { className: "h-4 w-4 mr-1" }),
6533
+ item.label
6534
+ ] }, i);
6535
+ }) })
5819
6536
  ] }),
5820
6537
  /* @__PURE__ */ jsxs37(
5821
6538
  Button,
@@ -5837,9 +6554,9 @@ function DetailPageHeader({
5837
6554
  // src/admin/pages/SubmissionDetailPage.tsx
5838
6555
  import { jsx as jsx47, jsxs as jsxs38 } from "react/jsx-runtime";
5839
6556
  function SubmissionDetailPage({ submissionId }) {
5840
- const [submission, setSubmission] = useState22(null);
5841
- const [loading, setLoading] = useState22(true);
5842
- const [error, setError] = useState22(null);
6557
+ const [submission, setSubmission] = useState23(null);
6558
+ const [loading, setLoading] = useState23(true);
6559
+ const [error, setError] = useState23(null);
5843
6560
  useEffect20(() => {
5844
6561
  async function load() {
5845
6562
  try {
@@ -5948,10 +6665,10 @@ function SubmissionDetailPage({ submissionId }) {
5948
6665
  }
5949
6666
 
5950
6667
  // src/admin/pages/OrderDetailPage.tsx
5951
- import { useEffect as useEffect21, useState as useState23 } from "react";
6668
+ import { useEffect as useEffect21, useState as useState24 } from "react";
5952
6669
  import Link10 from "next/link";
5953
- import { useRouter as useRouter6 } from "next/navigation";
5954
- import { X as X14 } from "lucide-react";
6670
+ import { useRouter as useRouter8 } from "next/navigation";
6671
+ import { X as X14, RefreshCw as RefreshCw2 } from "lucide-react";
5955
6672
 
5956
6673
  // src/components/Admin/DetailPageLayout.tsx
5957
6674
  import { jsx as jsx48, jsxs as jsxs39 } from "react/jsx-runtime";
@@ -5969,7 +6686,7 @@ function DetailPageLayout({
5969
6686
  }
5970
6687
 
5971
6688
  // src/admin/pages/OrderDetailPage.tsx
5972
- import { Fragment as Fragment7, jsx as jsx49, jsxs as jsxs40 } from "react/jsx-runtime";
6689
+ import { Fragment as Fragment8, jsx as jsx49, jsxs as jsxs40 } from "react/jsx-runtime";
5973
6690
  function formatMoney(amount, currency = "INR") {
5974
6691
  return new Intl.NumberFormat("en-IN", {
5975
6692
  style: "currency",
@@ -5992,10 +6709,12 @@ function formatAddress(a) {
5992
6709
  return parts.join(", ") || "\u2014";
5993
6710
  }
5994
6711
  function OrderDetailPage({ orderId }) {
5995
- const router = useRouter6();
5996
- const [order, setOrder] = useState23(null);
5997
- const [loading, setLoading] = useState23(true);
5998
- const [error, setError] = useState23(null);
6712
+ const router = useRouter8();
6713
+ const [order, setOrder] = useState24(null);
6714
+ const [loading, setLoading] = useState24(true);
6715
+ const [error, setError] = useState24(null);
6716
+ const [erpEnabled, setErpEnabled] = useState24(false);
6717
+ const [reposting, setReposting] = useState24(false);
5999
6718
  useEffect21(() => {
6000
6719
  async function load() {
6001
6720
  try {
@@ -6019,6 +6738,39 @@ function OrderDetailPage({ orderId }) {
6019
6738
  }
6020
6739
  load();
6021
6740
  }, [orderId]);
6741
+ useEffect21(() => {
6742
+ let cancelled = false;
6743
+ (async () => {
6744
+ try {
6745
+ const res = await fetch(`/api/orders/${orderId}/repost-erp`);
6746
+ if (!res.ok) return;
6747
+ const data = await res.json();
6748
+ if (!cancelled) setErpEnabled(data.enabled === true);
6749
+ } catch {
6750
+ }
6751
+ })();
6752
+ return () => {
6753
+ cancelled = true;
6754
+ };
6755
+ }, [orderId]);
6756
+ async function handleRepostToErp() {
6757
+ if (reposting) return;
6758
+ setReposting(true);
6759
+ setError(null);
6760
+ try {
6761
+ const res = await fetch(`/api/orders/${orderId}/repost-erp`, { method: "POST" });
6762
+ if (!res.ok) {
6763
+ const body = await res.json().catch(() => ({}));
6764
+ setError(body.error ?? "Failed to repost to ERP");
6765
+ return;
6766
+ }
6767
+ router.refresh();
6768
+ } catch {
6769
+ setError("Failed to repost to ERP");
6770
+ } finally {
6771
+ setReposting(false);
6772
+ }
6773
+ }
6022
6774
  if (loading) {
6023
6775
  return /* @__PURE__ */ jsx49("div", { className: "rounded-lg bg-white p-6 shadow-md", children: /* @__PURE__ */ jsx49("div", { className: "flex justify-center py-12", children: /* @__PURE__ */ jsx49("span", { className: "text-gray-500", children: "Loading..." }) }) });
6024
6776
  }
@@ -6041,13 +6793,14 @@ function OrderDetailPage({ orderId }) {
6041
6793
  {
6042
6794
  title: `Order ${order.orderNumber}`,
6043
6795
  subtitle: /* @__PURE__ */ jsx49("span", { className: "text-sm text-gray-400", children: formatDateTime(order.createdAt) }),
6044
- closeHref: "/admin/orders"
6796
+ closeHref: "/admin/orders",
6797
+ menuItems: erpEnabled ? [{ label: reposting ? "Reposting..." : "Repost to ERP", icon: RefreshCw2, onClick: handleRepostToErp }] : void 0
6045
6798
  }
6046
6799
  ),
6047
6800
  /* @__PURE__ */ jsx49(
6048
6801
  DetailPageLayout,
6049
6802
  {
6050
- main: /* @__PURE__ */ jsxs40(Fragment7, { children: [
6803
+ main: /* @__PURE__ */ jsxs40(Fragment8, { children: [
6051
6804
  /* @__PURE__ */ jsxs40("section", { children: [
6052
6805
  /* @__PURE__ */ jsx49("h2", { className: "text-xs font-semibold text-gray-400 uppercase tracking-wider mb-2", children: "Order details" }),
6053
6806
  /* @__PURE__ */ jsx49("div", { className: "min-w-0 overflow-hidden border border-gray-200 rounded-lg p-4 bg-gray-50/50", children: /* @__PURE__ */ jsxs40("dl", { className: "min-w-0 grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-3 text-sm", children: [
@@ -6079,7 +6832,7 @@ function OrderDetailPage({ orderId }) {
6079
6832
  /* @__PURE__ */ jsx49("dt", { className: "text-gray-500", children: "Total" }),
6080
6833
  /* @__PURE__ */ jsx49("dd", { className: "font-medium text-gray-900", children: formatMoney(Number(order.total), currency) })
6081
6834
  ] }),
6082
- (order.orderKind || order.parentOrderId != null) && /* @__PURE__ */ jsxs40(Fragment7, { children: [
6835
+ (order.orderKind || order.parentOrderId != null) && /* @__PURE__ */ jsxs40(Fragment8, { children: [
6083
6836
  /* @__PURE__ */ jsxs40("div", { className: "min-w-0", children: [
6084
6837
  /* @__PURE__ */ jsx49("dt", { className: "text-gray-500", children: "Kind" }),
6085
6838
  /* @__PURE__ */ jsx49("dd", { className: "font-medium text-gray-900 capitalize", children: order.orderKind ?? "sale" })
@@ -6202,7 +6955,7 @@ function OrderDetailPage({ orderId }) {
6202
6955
  ] })
6203
6956
  ] }) })
6204
6957
  ] }),
6205
- sidebar: /* @__PURE__ */ jsxs40(Fragment7, { children: [
6958
+ sidebar: /* @__PURE__ */ jsxs40(Fragment8, { children: [
6206
6959
  contact && /* @__PURE__ */ jsxs40("section", { children: [
6207
6960
  /* @__PURE__ */ jsx49("h2", { className: "text-xs font-semibold text-gray-400 uppercase tracking-wider mb-2", children: "Customer" }),
6208
6961
  /* @__PURE__ */ jsx49("div", { className: "min-w-0 overflow-hidden border border-gray-200 rounded-lg p-4 bg-gray-50/50", children: /* @__PURE__ */ jsxs40("dl", { className: "min-w-0 grid grid-cols-1 sm:grid-cols-3 gap-3 text-sm", children: [
@@ -6281,11 +7034,11 @@ function OrderDetailPage({ orderId }) {
6281
7034
  }
6282
7035
 
6283
7036
  // src/admin/pages/PaymentDetailPage.tsx
6284
- import { useEffect as useEffect22, useState as useState24 } from "react";
7037
+ import { useEffect as useEffect22, useState as useState25 } from "react";
6285
7038
  import Link11 from "next/link";
6286
- import { useRouter as useRouter7 } from "next/navigation";
7039
+ import { useRouter as useRouter9 } from "next/navigation";
6287
7040
  import { X as X15 } from "lucide-react";
6288
- import { Fragment as Fragment8, jsx as jsx50, jsxs as jsxs41 } from "react/jsx-runtime";
7041
+ import { Fragment as Fragment9, jsx as jsx50, jsxs as jsxs41 } from "react/jsx-runtime";
6289
7042
  function formatMoney2(amount, currency = "INR") {
6290
7043
  return new Intl.NumberFormat("en-IN", {
6291
7044
  style: "currency",
@@ -6294,10 +7047,10 @@ function formatMoney2(amount, currency = "INR") {
6294
7047
  }).format(Number(amount));
6295
7048
  }
6296
7049
  function PaymentDetailPage({ paymentId }) {
6297
- const router = useRouter7();
6298
- const [payment, setPayment] = useState24(null);
6299
- const [loading, setLoading] = useState24(true);
6300
- const [error, setError] = useState24(null);
7050
+ const router = useRouter9();
7051
+ const [payment, setPayment] = useState25(null);
7052
+ const [loading, setLoading] = useState25(true);
7053
+ const [error, setError] = useState25(null);
6301
7054
  useEffect22(() => {
6302
7055
  async function load() {
6303
7056
  try {
@@ -6347,7 +7100,7 @@ function PaymentDetailPage({ paymentId }) {
6347
7100
  /* @__PURE__ */ jsx50(
6348
7101
  DetailPageLayout,
6349
7102
  {
6350
- main: /* @__PURE__ */ jsxs41(Fragment8, { children: [
7103
+ main: /* @__PURE__ */ jsxs41(Fragment9, { children: [
6351
7104
  /* @__PURE__ */ jsxs41("section", { children: [
6352
7105
  /* @__PURE__ */ jsx50("h2", { className: "text-xs font-semibold text-gray-400 uppercase tracking-wider mb-2", children: "Payment details" }),
6353
7106
  /* @__PURE__ */ jsx50("div", { className: "min-w-0 overflow-hidden border border-gray-200 rounded-lg p-4 bg-gray-50/50", children: /* @__PURE__ */ jsxs41("dl", { className: "min-w-0 grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-3 text-sm", children: [
@@ -6410,7 +7163,7 @@ function PaymentDetailPage({ paymentId }) {
6410
7163
  ] })
6411
7164
  ] })
6412
7165
  ] }),
6413
- sidebar: /* @__PURE__ */ jsx50(Fragment8, { children: customer && /* @__PURE__ */ jsxs41("section", { children: [
7166
+ sidebar: /* @__PURE__ */ jsx50(Fragment9, { children: customer && /* @__PURE__ */ jsxs41("section", { children: [
6414
7167
  /* @__PURE__ */ jsx50("h2", { className: "text-xs font-semibold text-gray-400 uppercase tracking-wider mb-2", children: "Customer" }),
6415
7168
  /* @__PURE__ */ jsx50("div", { className: "min-w-0 overflow-hidden border border-gray-200 rounded-lg p-4 bg-gray-50/50", children: /* @__PURE__ */ jsxs41("dl", { className: "min-w-0 grid grid-cols-1 sm:grid-cols-3 gap-3 text-sm", children: [
6416
7169
  /* @__PURE__ */ jsxs41("div", { className: "min-w-0", children: [
@@ -6440,11 +7193,11 @@ function PaymentDetailPage({ paymentId }) {
6440
7193
  }
6441
7194
 
6442
7195
  // src/admin/pages/ContactDetailPage.tsx
6443
- import { useEffect as useEffect23, useState as useState25 } from "react";
7196
+ import { useEffect as useEffect23, useState as useState26 } from "react";
6444
7197
  import Link12 from "next/link";
6445
- import { useRouter as useRouter8 } from "next/navigation";
7198
+ import { useRouter as useRouter10 } from "next/navigation";
6446
7199
  import { Plus as Plus7, X as X16 } from "lucide-react";
6447
- import { Fragment as Fragment9, jsx as jsx51, jsxs as jsxs42 } from "react/jsx-runtime";
7200
+ import { Fragment as Fragment10, jsx as jsx51, jsxs as jsxs42 } from "react/jsx-runtime";
6448
7201
  function formatMoney3(amount, currency = "INR") {
6449
7202
  return new Intl.NumberFormat("en-IN", {
6450
7203
  style: "currency",
@@ -6458,13 +7211,13 @@ function formatAddress2(a) {
6458
7211
  }
6459
7212
  var ADDRESS_TAGS = [{ value: "", label: "\u2014" }, { value: "default", label: "Default" }, { value: "billing", label: "Billing" }, { value: "shipping", label: "Shipping" }];
6460
7213
  function ContactDetailPage({ contactId }) {
6461
- const router = useRouter8();
6462
- const [contact, setContact] = useState25(null);
6463
- const [loading, setLoading] = useState25(true);
6464
- const [error, setError] = useState25(null);
6465
- const [addAddressOpen, setAddAddressOpen] = useState25(false);
6466
- const [addAddressSaving, setAddAddressSaving] = useState25(false);
6467
- const [addAddressForm, setAddAddressForm] = useState25({
7214
+ const router = useRouter10();
7215
+ const [contact, setContact] = useState26(null);
7216
+ const [loading, setLoading] = useState26(true);
7217
+ const [error, setError] = useState26(null);
7218
+ const [addAddressOpen, setAddAddressOpen] = useState26(false);
7219
+ const [addAddressSaving, setAddAddressSaving] = useState26(false);
7220
+ const [addAddressForm, setAddAddressForm] = useState26({
6468
7221
  tag: "",
6469
7222
  line1: "",
6470
7223
  line2: "",
@@ -6556,7 +7309,7 @@ function ContactDetailPage({ contactId }) {
6556
7309
  /* @__PURE__ */ jsx51(
6557
7310
  DetailPageLayout,
6558
7311
  {
6559
- main: /* @__PURE__ */ jsxs42(Fragment9, { children: [
7312
+ main: /* @__PURE__ */ jsxs42(Fragment10, { children: [
6560
7313
  /* @__PURE__ */ jsxs42("section", { children: [
6561
7314
  /* @__PURE__ */ jsx51("h2", { className: "text-xs font-semibold text-gray-400 uppercase tracking-wider mb-2", children: "Contact details" }),
6562
7315
  /* @__PURE__ */ jsx51("div", { className: "min-w-0 overflow-hidden border border-gray-200 rounded-lg p-4 bg-gray-50/50", children: /* @__PURE__ */ jsxs42("dl", { className: "min-w-0 grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-3 text-sm", children: [
@@ -6572,7 +7325,7 @@ function ContactDetailPage({ contactId }) {
6572
7325
  /* @__PURE__ */ jsx51("dt", { className: "text-gray-500", children: "Phone" }),
6573
7326
  /* @__PURE__ */ jsx51("dd", { className: "font-medium text-gray-900 break-words", children: contact.phone ?? "\u2014" })
6574
7327
  ] }),
6575
- (contact.type ?? contact.company ?? contact.taxId) && /* @__PURE__ */ jsxs42(Fragment9, { children: [
7328
+ (contact.type ?? contact.company ?? contact.taxId) && /* @__PURE__ */ jsxs42(Fragment10, { children: [
6576
7329
  contact.type && /* @__PURE__ */ jsxs42("div", { className: "min-w-0", children: [
6577
7330
  /* @__PURE__ */ jsx51("dt", { className: "text-gray-500", children: "Type" }),
6578
7331
  /* @__PURE__ */ jsx51("dd", { className: "font-medium text-gray-900 break-words", children: contact.type })
@@ -6626,7 +7379,7 @@ function ContactDetailPage({ contactId }) {
6626
7379
  ] }) })
6627
7380
  ] })
6628
7381
  ] }),
6629
- sidebar: /* @__PURE__ */ jsxs42(Fragment9, { children: [
7382
+ sidebar: /* @__PURE__ */ jsxs42(Fragment10, { children: [
6630
7383
  /* @__PURE__ */ jsxs42("section", { children: [
6631
7384
  /* @__PURE__ */ jsx51("h2", { className: "text-xs font-semibold text-gray-400 uppercase tracking-wider mb-2", children: "Summary" }),
6632
7385
  /* @__PURE__ */ jsx51("div", { className: "min-w-0 overflow-hidden border border-gray-200 rounded-lg p-4 bg-gray-50/50", children: /* @__PURE__ */ jsxs42("dl", { className: "min-w-0 grid grid-cols-1 sm:grid-cols-3 gap-3 text-sm", children: [
@@ -6812,11 +7565,11 @@ function ContactDetailPage({ contactId }) {
6812
7565
  }
6813
7566
 
6814
7567
  // src/admin/pages/SettingsPage.tsx
6815
- import { useState as useState26, useEffect as useEffect24, useContext as useContext3 } from "react";
7568
+ import { useState as useState27, useEffect as useEffect24, useContext as useContext4 } from "react";
6816
7569
  import { useSearchParams as useSearchParams3 } from "next/navigation";
6817
- import { toast as toast2 } from "sonner";
7570
+ import { toast as toast3 } from "sonner";
6818
7571
  import { Save as Save3, RotateCcw } from "lucide-react";
6819
- import { Fragment as Fragment10, jsx as jsx52, jsxs as jsxs43 } from "react/jsx-runtime";
7572
+ import { Fragment as Fragment11, jsx as jsx52, jsxs as jsxs43 } from "react/jsx-runtime";
6820
7573
  var DEFAULTS = {
6821
7574
  primaryColor: "#313996",
6822
7575
  secondaryColor: "#6366f1",
@@ -6840,22 +7593,22 @@ function hexToHsl(hex) {
6840
7593
  function SettingsPage() {
6841
7594
  const searchParams = useSearchParams3();
6842
7595
  const tabParam = searchParams.get("tab");
6843
- const { theme, themeRegistry } = useContext3(AdminConfigContext);
6844
- const [tab, setTab] = useState26(
7596
+ const { theme, themeRegistry } = useContext4(AdminConfigContext);
7597
+ const [tab, setTab] = useState27(
6845
7598
  tabParam === "navbar" ? "navbar" : tabParam === "store" ? "store" : "appearance"
6846
7599
  );
6847
7600
  useEffect24(() => {
6848
7601
  if (tabParam === "navbar") setTab("navbar");
6849
7602
  else if (tabParam === "store") setTab("store");
6850
7603
  }, [tabParam]);
6851
- const [settings, setSettings] = useState26(DEFAULTS);
6852
- const [loading, setLoading] = useState26(true);
6853
- const [saving, setSaving] = useState26(false);
6854
- const [activeThemeId, setActiveThemeId] = useState26("");
6855
- const [navbarConfig, setNavbarConfig] = useState26({ logo: "", items: [], ctaLabel: "", ctaUrl: "" });
6856
- const [themeSettingsLoading, setThemeSettingsLoading] = useState26(true);
6857
- const [storeEnabled, setStoreEnabled] = useState26(false);
6858
- const [storeSettingsLoading, setStoreSettingsLoading] = useState26(true);
7604
+ const [settings, setSettings] = useState27(DEFAULTS);
7605
+ const [loading, setLoading] = useState27(true);
7606
+ const [saving, setSaving] = useState27(false);
7607
+ const [activeThemeId, setActiveThemeId] = useState27("");
7608
+ const [navbarConfig, setNavbarConfig] = useState27({ logo: "", items: [], ctaLabel: "", ctaUrl: "" });
7609
+ const [themeSettingsLoading, setThemeSettingsLoading] = useState27(true);
7610
+ const [storeEnabled, setStoreEnabled] = useState27(false);
7611
+ const [storeSettingsLoading, setStoreSettingsLoading] = useState27(true);
6859
7612
  useEffect24(() => {
6860
7613
  fetch("/api/settings/admin_view").then((r) => r.ok ? r.json() : {}).then((data) => {
6861
7614
  setSettings({
@@ -6901,9 +7654,9 @@ function SettingsPage() {
6901
7654
  document.documentElement.style.setProperty("--secondary", hexToHsl(settings.secondaryColor));
6902
7655
  if (settings.compactView === "true") document.documentElement.classList.add("compact");
6903
7656
  else document.documentElement.classList.remove("compact");
6904
- toast2.success("Settings saved");
7657
+ toast3.success("Settings saved");
6905
7658
  } catch {
6906
- toast2.error("Failed to save settings");
7659
+ toast3.error("Failed to save settings");
6907
7660
  } finally {
6908
7661
  setSaving(false);
6909
7662
  }
@@ -6917,10 +7670,10 @@ function SettingsPage() {
6917
7670
  headers: { "Content-Type": "application/json" },
6918
7671
  body: JSON.stringify({ activeThemeId: { value: id, type: "public" } })
6919
7672
  });
6920
- toast2.success("Theme updated");
7673
+ toast3.success("Theme updated");
6921
7674
  window.location.reload();
6922
7675
  } catch {
6923
- toast2.error("Failed to save theme");
7676
+ toast3.error("Failed to save theme");
6924
7677
  } finally {
6925
7678
  setSaving(false);
6926
7679
  }
@@ -6933,9 +7686,9 @@ function SettingsPage() {
6933
7686
  headers: { "Content-Type": "application/json" },
6934
7687
  body: JSON.stringify({ navbar: { value: JSON.stringify(navbarConfig), type: "public" } })
6935
7688
  });
6936
- toast2.success("Navbar saved");
7689
+ toast3.success("Navbar saved");
6937
7690
  } catch {
6938
- toast2.error("Failed to save");
7691
+ toast3.error("Failed to save");
6939
7692
  } finally {
6940
7693
  setSaving(false);
6941
7694
  }
@@ -6948,10 +7701,10 @@ function SettingsPage() {
6948
7701
  headers: { "Content-Type": "application/json" },
6949
7702
  body: JSON.stringify({ enabled: { value: storeEnabled ? "true" : "false", type: "public" } })
6950
7703
  });
6951
- toast2.success("Store settings saved");
7704
+ toast3.success("Store settings saved");
6952
7705
  window.location.reload();
6953
7706
  } catch {
6954
- toast2.error("Failed to save store settings");
7707
+ toast3.error("Failed to save store settings");
6955
7708
  } finally {
6956
7709
  setSaving(false);
6957
7710
  }
@@ -7027,7 +7780,7 @@ function SettingsPage() {
7027
7780
  /* @__PURE__ */ jsx52("span", { className: "text-[11px] text-gray-400", children: "Smaller spacing in admin" })
7028
7781
  ] }) })
7029
7782
  ] }),
7030
- tab === "navbar" && /* @__PURE__ */ jsx52("div", { className: "space-y-6", children: themeSettingsLoading ? /* @__PURE__ */ jsx52("div", { className: "flex items-center gap-2 text-gray-500", children: "Loading..." }) : /* @__PURE__ */ jsxs43(Fragment10, { children: [
7783
+ tab === "navbar" && /* @__PURE__ */ jsx52("div", { className: "space-y-6", children: themeSettingsLoading ? /* @__PURE__ */ jsx52("div", { className: "flex items-center gap-2 text-gray-500", children: "Loading..." }) : /* @__PURE__ */ jsxs43(Fragment11, { children: [
7031
7784
  /* @__PURE__ */ jsxs43("div", { children: [
7032
7785
  /* @__PURE__ */ jsx52("h2", { className: "text-lg font-semibold text-gray-900 mb-2", children: "Navbar & pages" }),
7033
7786
  /* @__PURE__ */ jsx52("p", { className: "text-sm text-gray-500 mb-4", children: "Set logo and menu items. Use parent/child (indent/outdent) for hierarchy. Each item can link to a page or a custom URL." }),
@@ -7035,7 +7788,7 @@ function SettingsPage() {
7035
7788
  ] }),
7036
7789
  /* @__PURE__ */ jsx52(Button, { onClick: handleSaveNavbar, disabled: saving, children: saving ? "Saving..." : "Save navbar" })
7037
7790
  ] }) }),
7038
- tab === "store" && /* @__PURE__ */ jsx52("div", { className: "space-y-6", children: storeSettingsLoading ? /* @__PURE__ */ jsx52("div", { className: "flex items-center gap-2 text-gray-500", children: "Loading..." }) : /* @__PURE__ */ jsxs43(Fragment10, { children: [
7791
+ tab === "store" && /* @__PURE__ */ jsx52("div", { className: "space-y-6", children: storeSettingsLoading ? /* @__PURE__ */ jsx52("div", { className: "flex items-center gap-2 text-gray-500", children: "Loading..." }) : /* @__PURE__ */ jsxs43(Fragment11, { children: [
7039
7792
  /* @__PURE__ */ jsxs43("div", { children: [
7040
7793
  /* @__PURE__ */ jsx52("h2", { className: "text-lg font-semibold text-gray-900 mb-2", children: "Store / E-commerce" }),
7041
7794
  /* @__PURE__ */ jsx52("p", { className: "text-sm text-gray-500 mb-4", children: "Enable e-commerce functionality to manage products, orders, payments, and more." }),
@@ -7067,11 +7820,39 @@ function SettingsPage() {
7067
7820
  }
7068
7821
 
7069
7822
  // src/admin/pages/MediaLibraryPage.tsx
7070
- import { useState as useState27, useEffect as useEffect25, useCallback as useCallback5, useRef as useRef8 } from "react";
7071
- import { Upload as Upload4, Search as Search5, Image as ImageIcon3, FileText as FileText2, Film, File as File3, Copy, Trash2 as Trash24, Edit2 } from "lucide-react";
7072
- import { toast as toast3 } from "sonner";
7073
- import { jsx as jsx53, jsxs as jsxs44 } from "react/jsx-runtime";
7074
- function getTypeCategory(mime) {
7823
+ import React17, { useState as useState28, useEffect as useEffect25, useCallback as useCallback5, useRef as useRef9 } from "react";
7824
+
7825
+ // src/lib/media-zip-extract.ts
7826
+ import { IsNull } from "typeorm";
7827
+ var ZIP_MIME_TYPES = /* @__PURE__ */ new Set(["application/zip", "application/x-zip-compressed"]);
7828
+ var MAX_TOTAL_UNCOMPRESSED = 80 * 1024 * 1024;
7829
+ function isZipMedia(mime, filename) {
7830
+ if (mime && ZIP_MIME_TYPES.has(mime)) return true;
7831
+ return filename.toLowerCase().endsWith(".zip");
7832
+ }
7833
+
7834
+ // src/admin/pages/MediaLibraryPage.tsx
7835
+ import {
7836
+ Upload as Upload4,
7837
+ Search as Search5,
7838
+ Image as ImageIcon3,
7839
+ FileText as FileText2,
7840
+ Film,
7841
+ File as File3,
7842
+ Copy,
7843
+ Trash2 as Trash24,
7844
+ Edit2,
7845
+ Folder,
7846
+ FolderPlus,
7847
+ Archive,
7848
+ LayoutGrid,
7849
+ List
7850
+ } from "lucide-react";
7851
+ import { toast as toast4 } from "sonner";
7852
+ import { Fragment as Fragment12, jsx as jsx53, jsxs as jsxs44 } from "react/jsx-runtime";
7853
+ function getTypeCategory(mime, kind, filename) {
7854
+ if (kind === "folder" || mime === "inode/directory") return "folder";
7855
+ if (isZipMedia(mime, filename ?? "")) return "zip";
7075
7856
  if (!mime) return "other";
7076
7857
  if (mime.startsWith("image/")) return "image";
7077
7858
  if (mime.startsWith("video/")) return "video";
@@ -7079,56 +7860,66 @@ function getTypeCategory(mime) {
7079
7860
  if (mime === "application/pdf" || mime.startsWith("application/")) return "document";
7080
7861
  return "other";
7081
7862
  }
7082
- function getTypeLabel(mime) {
7083
- const c = getTypeCategory(mime);
7863
+ function getTypeLabel(mime, kind, filename) {
7864
+ if (kind === "folder" || mime === "inode/directory") return "Folder";
7865
+ if (isZipMedia(mime, filename ?? "")) return "Zip";
7866
+ const c = getTypeCategory(mime, kind, filename);
7084
7867
  const labels = {
7085
7868
  image: "Image",
7086
7869
  video: "Video",
7087
7870
  audio: "Audio",
7088
7871
  document: "Document",
7872
+ folder: "Folder",
7873
+ zip: "Zip",
7089
7874
  other: "Other"
7090
7875
  };
7091
7876
  return labels[c] || "Other";
7092
7877
  }
7093
- function TypeIcon({ mimeType }) {
7094
- const c = getTypeCategory(mimeType);
7878
+ function TypeIcon({ mimeType, kind, filename }) {
7879
+ if (kind === "folder" || mimeType === "inode/directory") {
7880
+ return /* @__PURE__ */ jsx53(Folder, { className: "h-10 w-10 text-amber-500" });
7881
+ }
7882
+ if (isZipMedia(mimeType, filename ?? "")) {
7883
+ return /* @__PURE__ */ jsx53(Archive, { className: "h-10 w-10 text-violet-600" });
7884
+ }
7885
+ const c = getTypeCategory(mimeType, kind, filename);
7095
7886
  if (c === "image") return /* @__PURE__ */ jsx53(ImageIcon3, { className: "h-8 w-8 text-gray-400" });
7096
7887
  if (c === "video") return /* @__PURE__ */ jsx53(Film, { className: "h-8 w-8 text-gray-400" });
7097
7888
  if (c === "document") return /* @__PURE__ */ jsx53(FileText2, { className: "h-8 w-8 text-gray-400" });
7098
7889
  return /* @__PURE__ */ jsx53(File3, { className: "h-8 w-8 text-gray-400" });
7099
7890
  }
7100
- function groupByMonth(items) {
7101
- const groups = {};
7102
- items.forEach((item) => {
7103
- const d = new Date(item.createdAt);
7104
- const key = `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, "0")}`;
7105
- const label = d.toLocaleDateString("en-US", { year: "numeric", month: "long" });
7106
- if (!groups[label]) groups[label] = [];
7107
- groups[label].push(item);
7108
- });
7109
- return groups;
7110
- }
7111
7891
  function MediaLibraryPage() {
7112
- const [data, setData] = useState27([]);
7113
- const [loading, setLoading] = useState27(true);
7114
- const [page, setPage] = useState27(1);
7115
- const [totalPages, setTotalPages] = useState27(1);
7116
- const [search, setSearch] = useState27("");
7117
- const [searchInput, setSearchInput] = useState27("");
7118
- const [typeFilter, setTypeFilter] = useState27("");
7119
- const [uploading, setUploading] = useState27(false);
7120
- const [editModal, setEditModal] = useState27(null);
7121
- const [editAlt, setEditAlt] = useState27("");
7122
- const [editPublic, setEditPublic] = useState27(false);
7123
- const fileInputRef = useRef8(null);
7892
+ const [data, setData] = useState28([]);
7893
+ const [loading, setLoading] = useState28(true);
7894
+ const [page, setPage] = useState28(1);
7895
+ const [totalPages, setTotalPages] = useState28(1);
7896
+ const [search, setSearch] = useState28("");
7897
+ const [searchInput, setSearchInput] = useState28("");
7898
+ const [typeFilter, setTypeFilter] = useState28("");
7899
+ const [sortField, setSortField] = useState28("filename");
7900
+ const [sortOrder, setSortOrder] = useState28("asc");
7901
+ const [viewMode, setViewMode] = useState28("grid");
7902
+ const [uploading, setUploading] = useState28(false);
7903
+ const [currentParentId, setCurrentParentId] = useState28(null);
7904
+ const [crumb, setCrumb] = useState28([]);
7905
+ const [newFolderOpen, setNewFolderOpen] = useState28(false);
7906
+ const [newFolderName, setNewFolderName] = useState28("");
7907
+ const [editModal, setEditModal] = useState28(null);
7908
+ const [deleteTarget, setDeleteTarget] = useState28(null);
7909
+ const [editAlt, setEditAlt] = useState28("");
7910
+ const [editPublic, setEditPublic] = useState28(false);
7911
+ const [editFilename, setEditFilename] = useState28("");
7912
+ const [extractingId, setExtractingId] = useState28(null);
7913
+ const fileInputRef = useRef9(null);
7124
7914
  const load = useCallback5(async () => {
7125
7915
  setLoading(true);
7126
7916
  const params = new URLSearchParams({
7127
7917
  page: String(page),
7128
7918
  limit: "24",
7129
- sortField: "createdAt",
7130
- sortOrder: "desc"
7919
+ sortField,
7920
+ sortOrder
7131
7921
  });
7922
+ params.set("parentId", currentParentId === null ? "" : String(currentParentId));
7132
7923
  if (search) params.set("search", search);
7133
7924
  if (typeFilter) params.set("type", typeFilter);
7134
7925
  try {
@@ -7143,11 +7934,33 @@ function MediaLibraryPage() {
7143
7934
  } finally {
7144
7935
  setLoading(false);
7145
7936
  }
7146
- }, [page, search, typeFilter]);
7937
+ }, [page, search, typeFilter, currentParentId, sortField, sortOrder]);
7147
7938
  useEffect25(() => {
7148
7939
  load();
7149
7940
  }, [load]);
7150
7941
  const handleSearch = () => setSearch(searchInput.trim());
7942
+ const goRoot = useCallback5(() => {
7943
+ setPage(1);
7944
+ setCurrentParentId(null);
7945
+ setCrumb([]);
7946
+ }, []);
7947
+ const goCrumb = useCallback5((index) => {
7948
+ setPage(1);
7949
+ if (index < 0) {
7950
+ goRoot();
7951
+ return;
7952
+ }
7953
+ const slice = crumb.slice(0, index + 1);
7954
+ setCrumb(slice);
7955
+ const last = slice[slice.length - 1];
7956
+ setCurrentParentId(last.id);
7957
+ }, [crumb, goRoot]);
7958
+ const enterFolder = (item) => {
7959
+ if (item.kind !== "folder") return;
7960
+ setPage(1);
7961
+ setCurrentParentId(item.id);
7962
+ setCrumb((c) => [...c, { id: item.id, name: item.filename }]);
7963
+ };
7151
7964
  const handleUpload = async (e) => {
7152
7965
  const file = e.target.files?.[0];
7153
7966
  if (!file) return;
@@ -7155,6 +7968,7 @@ function MediaLibraryPage() {
7155
7968
  try {
7156
7969
  const formData = new FormData();
7157
7970
  formData.append("file", file);
7971
+ if (currentParentId != null) formData.append("parentId", String(currentParentId));
7158
7972
  const uploadRes = await fetch("/api/upload", { method: "POST", body: formData });
7159
7973
  const uploadJson = await uploadRes.json();
7160
7974
  if (!uploadRes.ok) throw new Error(uploadJson.error || "Upload failed");
@@ -7164,69 +7978,134 @@ function MediaLibraryPage() {
7164
7978
  method: "POST",
7165
7979
  headers: { "Content-Type": "application/json" },
7166
7980
  body: JSON.stringify({
7981
+ kind: "file",
7167
7982
  filename: file.name,
7168
7983
  url: filePath.startsWith("http") ? filePath : filePath,
7169
7984
  mimeType: file.type || "application/octet-stream",
7170
7985
  size: file.size,
7171
7986
  alt: null,
7172
- isPublic: false
7987
+ isPublic: false,
7988
+ parentId: currentParentId
7173
7989
  })
7174
7990
  });
7175
7991
  if (!createRes.ok) throw new Error("Failed to create media record");
7176
- toast3.success("File uploaded");
7992
+ toast4.success("File uploaded");
7177
7993
  load();
7178
7994
  } catch (err) {
7179
- toast3.error(err instanceof Error ? err.message : "Upload failed");
7995
+ toast4.error(err instanceof Error ? err.message : "Upload failed");
7180
7996
  } finally {
7181
7997
  setUploading(false);
7182
7998
  e.target.value = "";
7183
7999
  }
7184
8000
  };
7185
- const handleDelete = async (id) => {
7186
- if (!confirm("Delete this file?")) return;
8001
+ const createFolder = async () => {
8002
+ const name = newFolderName.trim();
8003
+ if (!name) {
8004
+ toast4.error("Enter a folder name");
8005
+ return;
8006
+ }
7187
8007
  try {
7188
- const res = await fetch(`/api/media/${id}`, { method: "DELETE" });
8008
+ const res = await fetch("/api/media", {
8009
+ method: "POST",
8010
+ headers: { "Content-Type": "application/json" },
8011
+ body: JSON.stringify({
8012
+ kind: "folder",
8013
+ filename: name,
8014
+ parentId: currentParentId
8015
+ })
8016
+ });
8017
+ const j = await res.json().catch(() => ({}));
8018
+ if (!res.ok) throw new Error(j.error || "Failed to create folder");
8019
+ toast4.success("Folder created");
8020
+ setNewFolderOpen(false);
8021
+ setNewFolderName("");
8022
+ load();
8023
+ } catch (err) {
8024
+ toast4.error(err instanceof Error ? err.message : "Failed");
8025
+ }
8026
+ };
8027
+ const handleExtractZip = async (id) => {
8028
+ setExtractingId(id);
8029
+ try {
8030
+ const res = await fetch(`/api/media/extract/${id}`, { method: "POST" });
8031
+ const j = await res.json().catch(() => ({}));
8032
+ if (!res.ok) throw new Error(j.error || "Extract failed");
8033
+ toast4.success(
8034
+ `Extracted ${j.files ?? 0} file(s)` + (j.folderEntries ? `, ${j.folderEntries} folder path(s)` : "")
8035
+ );
8036
+ load();
8037
+ } catch (e) {
8038
+ toast4.error(e instanceof Error ? e.message : "Extract failed");
8039
+ } finally {
8040
+ setExtractingId(null);
8041
+ }
8042
+ };
8043
+ const handleDelete = async (item) => {
8044
+ try {
8045
+ const res = await fetch(`/api/media/${item.id}`, { method: "DELETE" });
7189
8046
  if (!res.ok) throw new Error("Delete failed");
7190
- toast3.success("Deleted");
8047
+ toast4.success("Deleted");
8048
+ setDeleteTarget(null);
7191
8049
  load();
7192
8050
  } catch {
7193
- toast3.error("Delete failed");
8051
+ toast4.error("Delete failed");
7194
8052
  }
7195
8053
  };
7196
8054
  const handleSaveEdit = async () => {
7197
8055
  if (!editModal) return;
7198
8056
  try {
8057
+ const isFolder = editModal.kind === "folder";
8058
+ const body = isFolder ? { filename: editFilename.trim() || editModal.filename } : { alt: editAlt || null, isPublic: editPublic };
8059
+ if (isFolder && !body.filename) {
8060
+ toast4.error("Name required");
8061
+ return;
8062
+ }
7199
8063
  const res = await fetch(`/api/media/${editModal.id}`, {
7200
8064
  method: "PUT",
7201
8065
  headers: { "Content-Type": "application/json" },
7202
- body: JSON.stringify({ alt: editAlt || null, isPublic: editPublic })
8066
+ body: JSON.stringify(body)
7203
8067
  });
7204
8068
  if (!res.ok) throw new Error("Update failed");
7205
- toast3.success("Updated");
8069
+ toast4.success("Updated");
7206
8070
  setEditModal(null);
7207
8071
  load();
7208
8072
  } catch {
7209
- toast3.error("Update failed");
8073
+ toast4.error("Update failed");
7210
8074
  }
7211
8075
  };
7212
8076
  const copyUrl = (url) => {
7213
8077
  const full = url.startsWith("http") ? url : `${typeof window !== "undefined" ? window.location.origin : ""}${url}`;
7214
8078
  navigator.clipboard.writeText(full);
7215
- toast3.success("URL copied");
8079
+ toast4.success("URL copied");
7216
8080
  };
7217
8081
  const openEdit = (item) => {
7218
8082
  setEditModal(item);
7219
8083
  setEditAlt(item.alt || "");
7220
8084
  setEditPublic(item.isPublic);
8085
+ setEditFilename(item.filename);
7221
8086
  };
7222
- const grouped = groupByMonth(data);
7223
- const isImage = (mime) => getTypeCategory(mime) === "image";
8087
+ const isImage = (mime, kind, filename) => kind !== "folder" && getTypeCategory(mime, kind, filename) === "image";
8088
+ const listViewData = React17.useMemo(() => {
8089
+ const sorted = [...data];
8090
+ const byDateDesc = (a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime();
8091
+ const folders = sorted.filter((x) => x.kind === "folder").sort(byDateDesc);
8092
+ const files = sorted.filter((x) => x.kind !== "folder").sort(byDateDesc);
8093
+ return [...folders, ...files];
8094
+ }, [data]);
7224
8095
  return /* @__PURE__ */ jsxs44("div", { className: "min-w-0 rounded-lg bg-white shadow-md", children: [
7225
8096
  /* @__PURE__ */ jsxs44("div", { className: "bg-gray-800 border-b border-gray-700 px-4 py-2.5 rounded-t-lg", children: [
7226
8097
  /* @__PURE__ */ jsx53("h1", { className: "text-base font-semibold text-white", children: "Media Library" }),
7227
- /* @__PURE__ */ jsx53("p", { className: "text-xs text-gray-300 mt-0.5", children: "Upload and manage files. Group by type or date." })
8098
+ /* @__PURE__ */ jsx53("p", { className: "text-xs text-gray-300 mt-0.5", children: "Folders and files (Google Drive\u2013style). Storage mirrors the folder tree under uploads/." })
7228
8099
  ] }),
7229
8100
  /* @__PURE__ */ jsxs44("div", { className: "min-w-0 p-4 space-y-3", children: [
8101
+ /* @__PURE__ */ jsxs44("div", { className: "flex flex-wrap items-center gap-2 text-sm text-gray-700", children: [
8102
+ /* @__PURE__ */ jsx53("span", { className: "font-medium text-gray-600", children: "Location:" }),
8103
+ /* @__PURE__ */ jsx53("button", { type: "button", className: "text-blue-600 hover:underline", onClick: () => goCrumb(-1), children: "Media" }),
8104
+ crumb.map((c, i) => /* @__PURE__ */ jsxs44("span", { className: "flex items-center gap-1", children: [
8105
+ /* @__PURE__ */ jsx53("span", { className: "text-gray-400", children: "/" }),
8106
+ /* @__PURE__ */ jsx53("button", { type: "button", className: "text-blue-600 hover:underline", onClick: () => goCrumb(i), children: c.name })
8107
+ ] }, `${c.id}-${i}`))
8108
+ ] }),
7230
8109
  /* @__PURE__ */ jsxs44("div", { className: "flex flex-wrap items-center gap-3", children: [
7231
8110
  /* @__PURE__ */ jsx53(
7232
8111
  "input",
@@ -7236,7 +8115,7 @@ function MediaLibraryPage() {
7236
8115
  className: "hidden",
7237
8116
  onChange: handleUpload,
7238
8117
  disabled: uploading,
7239
- accept: "image/*,video/*,audio/*,.pdf,.doc,.docx"
8118
+ accept: "image/*,video/*,audio/*,.pdf,.doc,.docx,.zip"
7240
8119
  }
7241
8120
  ),
7242
8121
  /* @__PURE__ */ jsxs44(
@@ -7252,11 +8131,15 @@ function MediaLibraryPage() {
7252
8131
  ]
7253
8132
  }
7254
8133
  ),
8134
+ /* @__PURE__ */ jsxs44(Button, { type: "button", variant: "secondary", className: "flex items-center gap-2", onClick: () => setNewFolderOpen(true), children: [
8135
+ /* @__PURE__ */ jsx53(FolderPlus, { className: "h-4 w-4" }),
8136
+ "New folder"
8137
+ ] }),
7255
8138
  /* @__PURE__ */ jsxs44("div", { className: "flex items-center gap-2 flex-1 min-w-[200px]", children: [
7256
8139
  /* @__PURE__ */ jsx53(
7257
8140
  Input,
7258
8141
  {
7259
- placeholder: "Search by filename...",
8142
+ placeholder: "Search by name...",
7260
8143
  value: searchInput,
7261
8144
  onChange: (e) => setSearchInput(e.target.value),
7262
8145
  onKeyDown: (e) => e.key === "Enter" && handleSearch()
@@ -7278,61 +8161,192 @@ function MediaLibraryPage() {
7278
8161
  /* @__PURE__ */ jsx53("option", { value: "application", children: "Documents" })
7279
8162
  ]
7280
8163
  }
7281
- )
8164
+ ),
8165
+ /* @__PURE__ */ jsxs44(
8166
+ "select",
8167
+ {
8168
+ className: "border rounded-md px-3 py-2 text-sm bg-white max-w-[200px]",
8169
+ value: `${sortField}:${sortOrder}`,
8170
+ onChange: (e) => {
8171
+ const [f, o] = e.target.value.split(":");
8172
+ setSortField(f);
8173
+ setSortOrder(o);
8174
+ setPage(1);
8175
+ },
8176
+ children: [
8177
+ /* @__PURE__ */ jsx53("option", { value: "filename:asc", children: "Name A\u2013Z" }),
8178
+ /* @__PURE__ */ jsx53("option", { value: "filename:desc", children: "Name Z\u2013A" }),
8179
+ /* @__PURE__ */ jsx53("option", { value: "createdAt:desc", children: "Newest first" }),
8180
+ /* @__PURE__ */ jsx53("option", { value: "createdAt:asc", children: "Oldest first" })
8181
+ ]
8182
+ }
8183
+ ),
8184
+ /* @__PURE__ */ jsxs44("div", { className: "inline-flex rounded-md border border-gray-300 overflow-hidden bg-white", children: [
8185
+ /* @__PURE__ */ jsxs44(
8186
+ "button",
8187
+ {
8188
+ type: "button",
8189
+ className: `px-2.5 py-2 text-xs inline-flex items-center gap-1 ${viewMode === "grid" ? "bg-gray-100 text-gray-900" : "text-gray-600"}`,
8190
+ onClick: () => setViewMode("grid"),
8191
+ title: "Grid view",
8192
+ children: [
8193
+ /* @__PURE__ */ jsx53(LayoutGrid, { className: "h-4 w-4" }),
8194
+ "Grid"
8195
+ ]
8196
+ }
8197
+ ),
8198
+ /* @__PURE__ */ jsxs44(
8199
+ "button",
8200
+ {
8201
+ type: "button",
8202
+ className: `px-2.5 py-2 text-xs inline-flex items-center gap-1 border-l border-gray-300 ${viewMode === "list" ? "bg-gray-100 text-gray-900" : "text-gray-600"}`,
8203
+ onClick: () => setViewMode("list"),
8204
+ title: "List view",
8205
+ children: [
8206
+ /* @__PURE__ */ jsx53(List, { className: "h-4 w-4" }),
8207
+ "List"
8208
+ ]
8209
+ }
8210
+ )
8211
+ ] })
7282
8212
  ] }),
7283
- loading ? /* @__PURE__ */ jsx53("div", { className: "flex justify-center py-12", children: /* @__PURE__ */ jsx53("div", { className: "animate-spin rounded-full h-8 w-8 border-2 border-gray-300 border-t-gray-600" }) }) : data.length === 0 ? /* @__PURE__ */ jsx53("div", { className: "text-center py-12 text-gray-500", children: "No media yet. Upload a file to get started." }) : /* @__PURE__ */ jsx53("div", { className: "space-y-8", children: Object.entries(grouped).map(([monthLabel, items]) => /* @__PURE__ */ jsxs44("div", { children: [
7284
- /* @__PURE__ */ jsx53("h2", { className: "text-sm font-semibold text-gray-500 uppercase tracking-wider mb-3", children: monthLabel }),
7285
- /* @__PURE__ */ jsx53("div", { className: "grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-6 gap-4", children: items.map((item) => /* @__PURE__ */ jsxs44(
8213
+ loading ? /* @__PURE__ */ jsx53("div", { className: "flex justify-center py-12", children: /* @__PURE__ */ jsx53("div", { className: "animate-spin rounded-full h-8 w-8 border-2 border-gray-300 border-t-gray-600" }) }) : data.length === 0 ? /* @__PURE__ */ jsx53("div", { className: "text-center py-12 text-gray-500", children: "This folder is empty. Create a folder or upload a file." }) : viewMode === "grid" ? /* @__PURE__ */ jsx53("div", { className: "grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-6 gap-4", children: data.map((item) => {
8214
+ const isF = item.kind === "folder";
8215
+ return /* @__PURE__ */ jsxs44(
7286
8216
  "div",
7287
8217
  {
7288
8218
  className: "border rounded-lg overflow-hidden bg-gray-50 hover:bg-gray-100 transition-colors group",
7289
8219
  children: [
7290
- /* @__PURE__ */ jsxs44("div", { className: "aspect-square flex items-center justify-center bg-gray-200 relative", children: [
7291
- isImage(item.mimeType) ? /* @__PURE__ */ jsx53(
7292
- "img",
7293
- {
7294
- src: item.url,
7295
- alt: item.alt || item.filename,
7296
- className: "w-full h-full object-cover"
7297
- }
7298
- ) : /* @__PURE__ */ jsx53(TypeIcon, { mimeType: item.mimeType }),
7299
- /* @__PURE__ */ jsxs44("div", { className: "absolute inset-0 bg-black/0 group-hover:bg-black/40 transition-colors flex items-center justify-center gap-1 opacity-0 group-hover:opacity-100", children: [
7300
- /* @__PURE__ */ jsx53(
7301
- Button,
7302
- {
7303
- size: "icon",
7304
- variant: "secondary",
7305
- className: "h-8 w-8",
7306
- onClick: () => copyUrl(item.url),
7307
- children: /* @__PURE__ */ jsx53(Copy, { className: "h-3 w-3" })
7308
- }
7309
- ),
7310
- /* @__PURE__ */ jsx53(Button, { size: "icon", variant: "secondary", className: "h-8 w-8", onClick: () => openEdit(item), children: /* @__PURE__ */ jsx53(Edit2, { className: "h-3 w-3" }) }),
7311
- /* @__PURE__ */ jsx53(
7312
- Button,
7313
- {
7314
- size: "icon",
7315
- variant: "destructive",
7316
- className: "h-8 w-8",
7317
- onClick: () => handleDelete(item.id),
7318
- children: /* @__PURE__ */ jsx53(Trash24, { className: "h-3 w-3" })
7319
- }
7320
- )
7321
- ] })
7322
- ] }),
8220
+ /* @__PURE__ */ jsxs44(
8221
+ "button",
8222
+ {
8223
+ type: "button",
8224
+ className: "w-full aspect-square flex items-center justify-center bg-gray-200 relative cursor-pointer",
8225
+ onClick: () => isF && enterFolder(item),
8226
+ children: [
8227
+ isImage(item.mimeType, item.kind, item.filename) ? /* @__PURE__ */ jsx53(
8228
+ "img",
8229
+ {
8230
+ src: item.url,
8231
+ alt: item.alt || item.filename,
8232
+ className: "w-full h-full object-cover"
8233
+ }
8234
+ ) : /* @__PURE__ */ jsx53(TypeIcon, { mimeType: item.mimeType, kind: item.kind, filename: item.filename }),
8235
+ /* @__PURE__ */ jsxs44("div", { className: "absolute inset-0 bg-black/0 group-hover:bg-black/40 transition-colors flex items-center justify-center gap-1 opacity-0 group-hover:opacity-100 flex-wrap", children: [
8236
+ !isF && isZipMedia(item.mimeType, item.filename) ? /* @__PURE__ */ jsx53(
8237
+ Button,
8238
+ {
8239
+ size: "icon",
8240
+ variant: "outline",
8241
+ className: "h-8 w-8",
8242
+ title: "Extract zip into this folder",
8243
+ disabled: extractingId === item.id,
8244
+ onClick: (e) => {
8245
+ e.stopPropagation();
8246
+ handleExtractZip(item.id);
8247
+ },
8248
+ children: /* @__PURE__ */ jsx53(Archive, { className: "h-3 w-3" })
8249
+ }
8250
+ ) : null,
8251
+ !isF && item.url ? /* @__PURE__ */ jsx53(
8252
+ Button,
8253
+ {
8254
+ size: "icon",
8255
+ variant: "outline",
8256
+ className: "h-8 w-8",
8257
+ onClick: (e) => {
8258
+ e.stopPropagation();
8259
+ copyUrl(item.url);
8260
+ },
8261
+ children: /* @__PURE__ */ jsx53(Copy, { className: "h-3 w-3" })
8262
+ }
8263
+ ) : null,
8264
+ /* @__PURE__ */ jsx53(
8265
+ Button,
8266
+ {
8267
+ size: "icon",
8268
+ variant: "outline",
8269
+ className: "h-8 w-8",
8270
+ onClick: (e) => {
8271
+ e.stopPropagation();
8272
+ openEdit(item);
8273
+ },
8274
+ children: /* @__PURE__ */ jsx53(Edit2, { className: "h-3 w-3" })
8275
+ }
8276
+ ),
8277
+ /* @__PURE__ */ jsx53(
8278
+ Button,
8279
+ {
8280
+ size: "icon",
8281
+ variant: "outline",
8282
+ className: "h-8 w-8 border-red-300 text-red-600 hover:text-red-700",
8283
+ onClick: (e) => {
8284
+ e.stopPropagation();
8285
+ setDeleteTarget(item);
8286
+ },
8287
+ children: /* @__PURE__ */ jsx53(Trash24, { className: "h-3 w-3" })
8288
+ }
8289
+ )
8290
+ ] })
8291
+ ]
8292
+ }
8293
+ ),
7323
8294
  /* @__PURE__ */ jsxs44("div", { className: "p-2", children: [
7324
- /* @__PURE__ */ jsx53("p", { className: "text-xs font-medium text-gray-900 truncate", title: item.filename, children: item.filename }),
8295
+ /* @__PURE__ */ jsx53("p", { className: "text-xs font-medium text-gray-900 truncate text-left", title: item.filename, children: item.filename }),
7325
8296
  /* @__PURE__ */ jsxs44("div", { className: "flex items-center justify-between mt-1", children: [
7326
8297
  /* @__PURE__ */ jsx53("span", { className: "text-xs text-gray-500", children: formatDate(item.createdAt) }),
7327
- /* @__PURE__ */ jsx53("span", { className: "text-xs px-1.5 py-0.5 rounded bg-gray-200 text-gray-600", children: getTypeLabel(item.mimeType) })
8298
+ /* @__PURE__ */ jsx53("span", { className: "text-xs px-1.5 py-0.5 rounded bg-gray-200 text-gray-600", children: getTypeLabel(item.mimeType, item.kind, item.filename) })
7328
8299
  ] }),
7329
- item.isPublic && /* @__PURE__ */ jsx53("span", { className: "text-xs text-green-600 mt-0.5 block", children: "Public" })
8300
+ item.isPublic && !isF && /* @__PURE__ */ jsx53("span", { className: "text-xs text-green-600 mt-0.5 block", children: "Public" }),
8301
+ isF && /* @__PURE__ */ jsx53(
8302
+ "button",
8303
+ {
8304
+ type: "button",
8305
+ className: "text-xs text-blue-600 mt-1 hover:underline",
8306
+ onClick: () => enterFolder(item),
8307
+ children: "Open"
8308
+ }
8309
+ )
7330
8310
  ] })
7331
8311
  ]
7332
8312
  },
7333
8313
  item.id
7334
- )) })
7335
- ] }, monthLabel)) }),
8314
+ );
8315
+ }) }) : /* @__PURE__ */ jsx53("div", { className: "overflow-x-auto rounded-md border border-gray-200 bg-white", children: /* @__PURE__ */ jsxs44("table", { className: "w-full text-sm", children: [
8316
+ /* @__PURE__ */ jsx53("thead", { children: /* @__PURE__ */ jsxs44("tr", { className: "border-b bg-gray-50", children: [
8317
+ /* @__PURE__ */ jsx53("th", { className: "p-3 text-left font-medium", children: "Name" }),
8318
+ /* @__PURE__ */ jsx53("th", { className: "p-3 text-left font-medium", children: "Type" }),
8319
+ /* @__PURE__ */ jsx53("th", { className: "p-3 text-left font-medium", children: "Created" }),
8320
+ /* @__PURE__ */ jsx53("th", { className: "p-3 text-left font-medium", children: "Size" }),
8321
+ /* @__PURE__ */ jsx53("th", { className: "p-3 text-right font-medium", children: "Actions" })
8322
+ ] }) }),
8323
+ /* @__PURE__ */ jsx53("tbody", { children: listViewData.map((item) => {
8324
+ const isF = item.kind === "folder";
8325
+ return /* @__PURE__ */ jsxs44("tr", { className: "border-b border-gray-100 hover:bg-gray-50", children: [
8326
+ /* @__PURE__ */ jsx53("td", { className: "p-3", children: /* @__PURE__ */ jsxs44(
8327
+ "button",
8328
+ {
8329
+ type: "button",
8330
+ className: `inline-flex items-center gap-2 ${isF ? "text-blue-600 hover:underline" : "text-gray-900"}`,
8331
+ onClick: () => isF && enterFolder(item),
8332
+ children: [
8333
+ /* @__PURE__ */ jsx53(TypeIcon, { mimeType: item.mimeType, kind: item.kind, filename: item.filename }),
8334
+ /* @__PURE__ */ jsx53("span", { className: "truncate max-w-[260px]", title: item.filename, children: item.filename })
8335
+ ]
8336
+ }
8337
+ ) }),
8338
+ /* @__PURE__ */ jsx53("td", { className: "p-3 text-gray-600", children: getTypeLabel(item.mimeType, item.kind, item.filename) }),
8339
+ /* @__PURE__ */ jsx53("td", { className: "p-3 text-gray-600", children: formatDate(item.createdAt) }),
8340
+ /* @__PURE__ */ jsx53("td", { className: "p-3 text-gray-600", children: isF ? "\u2014" : `${Math.round((item.size || 0) / 1024)} KB` }),
8341
+ /* @__PURE__ */ jsx53("td", { className: "p-3", children: /* @__PURE__ */ jsxs44("div", { className: "flex items-center justify-end gap-1", children: [
8342
+ !isF && isZipMedia(item.mimeType, item.filename) && /* @__PURE__ */ jsx53(Button, { size: "icon", variant: "outline", className: "h-8 w-8", onClick: () => handleExtractZip(item.id), disabled: extractingId === item.id, children: /* @__PURE__ */ jsx53(Archive, { className: "h-3 w-3" }) }),
8343
+ !isF && item.url && /* @__PURE__ */ jsx53(Button, { size: "icon", variant: "outline", className: "h-8 w-8", onClick: () => copyUrl(item.url), children: /* @__PURE__ */ jsx53(Copy, { className: "h-3 w-3" }) }),
8344
+ /* @__PURE__ */ jsx53(Button, { size: "icon", variant: "outline", className: "h-8 w-8", onClick: () => openEdit(item), children: /* @__PURE__ */ jsx53(Edit2, { className: "h-3 w-3" }) }),
8345
+ /* @__PURE__ */ jsx53(Button, { size: "icon", variant: "outline", className: "h-8 w-8 border-red-300 text-red-600 hover:text-red-700", onClick: () => setDeleteTarget(item), children: /* @__PURE__ */ jsx53(Trash24, { className: "h-3 w-3" }) })
8346
+ ] }) })
8347
+ ] }, item.id);
8348
+ }) })
8349
+ ] }) }),
7336
8350
  totalPages > 1 && /* @__PURE__ */ jsx53(Pagination, { className: "mt-6", children: /* @__PURE__ */ jsxs44(PaginationContent, { children: [
7337
8351
  /* @__PURE__ */ jsx53(PaginationItem, { children: /* @__PURE__ */ jsx53(
7338
8352
  PaginationPrevious,
@@ -7354,9 +8368,28 @@ function MediaLibraryPage() {
7354
8368
  ) })
7355
8369
  ] }) })
7356
8370
  ] }),
8371
+ /* @__PURE__ */ jsx53(Dialog, { open: newFolderOpen, onOpenChange: setNewFolderOpen, children: /* @__PURE__ */ jsxs44(DialogContent, { children: [
8372
+ /* @__PURE__ */ jsx53(DialogHeader, { children: /* @__PURE__ */ jsx53(DialogTitle, { children: "New folder" }) }),
8373
+ /* @__PURE__ */ jsx53(
8374
+ Input,
8375
+ {
8376
+ placeholder: "Folder name",
8377
+ value: newFolderName,
8378
+ onChange: (e) => setNewFolderName(e.target.value),
8379
+ onKeyDown: (e) => e.key === "Enter" && createFolder()
8380
+ }
8381
+ ),
8382
+ /* @__PURE__ */ jsxs44(DialogFooter, { children: [
8383
+ /* @__PURE__ */ jsx53(Button, { variant: "outline", onClick: () => setNewFolderOpen(false), children: "Cancel" }),
8384
+ /* @__PURE__ */ jsx53(Button, { onClick: createFolder, children: "Create" })
8385
+ ] })
8386
+ ] }) }),
7357
8387
  /* @__PURE__ */ jsx53(Dialog, { open: !!editModal, onOpenChange: (open) => !open && setEditModal(null), children: /* @__PURE__ */ jsxs44(DialogContent, { children: [
7358
- /* @__PURE__ */ jsx53(DialogHeader, { children: /* @__PURE__ */ jsx53(DialogTitle, { children: "Edit media" }) }),
7359
- editModal && /* @__PURE__ */ jsxs44("div", { className: "space-y-4 py-2", children: [
8388
+ /* @__PURE__ */ jsx53(DialogHeader, { children: /* @__PURE__ */ jsx53(DialogTitle, { children: editModal?.kind === "folder" ? "Rename folder" : "Edit media" }) }),
8389
+ editModal && /* @__PURE__ */ jsx53("div", { className: "space-y-4 py-2", children: editModal.kind === "folder" ? /* @__PURE__ */ jsxs44("div", { children: [
8390
+ /* @__PURE__ */ jsx53("label", { className: "text-sm font-medium", children: "Name" }),
8391
+ /* @__PURE__ */ jsx53(Input, { value: editFilename, onChange: (e) => setEditFilename(e.target.value), className: "mt-1" })
8392
+ ] }) : /* @__PURE__ */ jsxs44(Fragment12, { children: [
7360
8393
  /* @__PURE__ */ jsxs44("div", { children: [
7361
8394
  /* @__PURE__ */ jsx53("label", { className: "text-sm font-medium", children: "Alt text" }),
7362
8395
  /* @__PURE__ */ jsx53(
@@ -7381,20 +8414,37 @@ function MediaLibraryPage() {
7381
8414
  ),
7382
8415
  /* @__PURE__ */ jsx53("label", { htmlFor: "edit-public", className: "text-sm", children: "Public (visible on site)" })
7383
8416
  ] })
7384
- ] }),
8417
+ ] }) }),
7385
8418
  /* @__PURE__ */ jsxs44(DialogFooter, { children: [
7386
8419
  /* @__PURE__ */ jsx53(Button, { variant: "outline", onClick: () => setEditModal(null), children: "Cancel" }),
7387
8420
  /* @__PURE__ */ jsx53(Button, { onClick: handleSaveEdit, children: "Save" })
7388
8421
  ] })
8422
+ ] }) }),
8423
+ /* @__PURE__ */ jsx53(Dialog, { open: !!deleteTarget, onOpenChange: (open) => !open && setDeleteTarget(null), children: /* @__PURE__ */ jsxs44(DialogContent, { children: [
8424
+ /* @__PURE__ */ jsx53(DialogHeader, { children: /* @__PURE__ */ jsx53(DialogTitle, { children: "Confirm Delete" }) }),
8425
+ /* @__PURE__ */ jsx53("p", { className: "text-sm text-gray-600", children: deleteTarget?.kind === "folder" ? "Delete this folder and everything inside it?" : "Delete this file?" }),
8426
+ /* @__PURE__ */ jsxs44(DialogFooter, { children: [
8427
+ /* @__PURE__ */ jsx53(Button, { variant: "outline", onClick: () => setDeleteTarget(null), children: "Cancel" }),
8428
+ /* @__PURE__ */ jsx53(
8429
+ Button,
8430
+ {
8431
+ variant: "destructive",
8432
+ onClick: () => {
8433
+ if (deleteTarget) handleDelete(deleteTarget);
8434
+ },
8435
+ children: "Delete"
8436
+ }
8437
+ )
8438
+ ] })
7389
8439
  ] }) })
7390
8440
  ] });
7391
8441
  }
7392
8442
 
7393
8443
  // src/admin/pages/PageBuilderPage.tsx
7394
- import { useState as useState28, useEffect as useEffect26, useContext as useContext4, useRef as useRef9 } from "react";
8444
+ import { useState as useState29, useEffect as useEffect26, useContext as useContext5, useRef as useRef10 } from "react";
7395
8445
  import { Editor, Frame, Element, useEditor, useNode } from "@craftjs/core";
7396
8446
  import { Save as Save4, X as X17, ChevronDown as ChevronDown5, ChevronRight as ChevronRight4, LayoutDashboard as LayoutDashboard3, Layers as Layers2, Box, SlidersHorizontal } from "lucide-react";
7397
- import { useRouter as useRouter9 } from "next/navigation";
8447
+ import { useRouter as useRouter11 } from "next/navigation";
7398
8448
 
7399
8449
  // src/theme/registry.ts
7400
8450
  function buildResolver(theme) {
@@ -7420,7 +8470,7 @@ function getCatalog(theme) {
7420
8470
  // src/admin/pages/PageBuilderPage.tsx
7421
8471
  import * as LucideIcons from "lucide-react";
7422
8472
  import React18 from "react";
7423
- import { Fragment as Fragment11, jsx as jsx54, jsxs as jsxs45 } from "react/jsx-runtime";
8473
+ import { Fragment as Fragment13, jsx as jsx54, jsxs as jsxs45 } from "react/jsx-runtime";
7424
8474
  function createSelectable(Comp) {
7425
8475
  function SelectableWrapper(props) {
7426
8476
  const { id, connectors, displayName, isHovered } = useNode((node) => ({
@@ -7464,7 +8514,7 @@ function DraggableCatalogItem({
7464
8514
  Icon: Icon2,
7465
8515
  description
7466
8516
  }) {
7467
- const elRef = useRef9(null);
8517
+ const elRef = useRef10(null);
7468
8518
  useEffect26(() => {
7469
8519
  if (!elRef.current) return;
7470
8520
  if (meta.canContainChildren) {
@@ -7492,7 +8542,7 @@ function DraggableCatalogItem({
7492
8542
  function ComponentPickerContent({ theme, resolver }) {
7493
8543
  const { connectors } = useEditor();
7494
8544
  const catalog = getCatalog(theme);
7495
- const [collapsed, setCollapsed] = useState28({});
8545
+ const [collapsed, setCollapsed] = useState29({});
7496
8546
  const toggleCategory = (cat) => {
7497
8547
  setCollapsed((prev) => ({ ...prev, [cat]: !prev[cat] }));
7498
8548
  };
@@ -7697,7 +8747,7 @@ function LayersPanelContent() {
7697
8747
  nodes: state.nodes,
7698
8748
  selectedSet: state.events.selected
7699
8749
  }));
7700
- const [expanded, setExpanded] = useState28({});
8750
+ const [expanded, setExpanded] = useState29({});
7701
8751
  const nodeMap = nodes || {};
7702
8752
  const rootId = (() => {
7703
8753
  const ids = Object.keys(nodeMap);
@@ -7819,10 +8869,10 @@ function CollapsibleSection({
7819
8869
  ] });
7820
8870
  }
7821
8871
  function RightSidebar({ theme, resolver, activeTab, setActiveTab, seoProps }) {
7822
- const [componentsOpen, setComponentsOpen] = useState28(true);
7823
- const [propertiesOpen, setPropertiesOpen] = useState28(true);
7824
- const [layoutOpen, setLayoutOpen] = useState28(true);
7825
- const [layersOpen, setLayersOpen] = useState28(true);
8872
+ const [componentsOpen, setComponentsOpen] = useState29(true);
8873
+ const [propertiesOpen, setPropertiesOpen] = useState29(true);
8874
+ const [layoutOpen, setLayoutOpen] = useState29(true);
8875
+ const [layersOpen, setLayersOpen] = useState29(true);
7826
8876
  return /* @__PURE__ */ jsxs45("div", { className: "flex flex-col flex-1 overflow-hidden", children: [
7827
8877
  /* @__PURE__ */ jsx54("div", { className: "flex border-b flex-shrink-0", children: ["designer", "seo"].map((tab) => /* @__PURE__ */ jsx54(
7828
8878
  "button",
@@ -7834,7 +8884,7 @@ function RightSidebar({ theme, resolver, activeTab, setActiveTab, seoProps }) {
7834
8884
  tab
7835
8885
  )) }),
7836
8886
  /* @__PURE__ */ jsxs45("div", { className: "flex-1 overflow-y-auto flex flex-col min-h-0", children: [
7837
- activeTab === "designer" && /* @__PURE__ */ jsxs45(Fragment11, { children: [
8887
+ activeTab === "designer" && /* @__PURE__ */ jsxs45(Fragment13, { children: [
7838
8888
  /* @__PURE__ */ jsx54(
7839
8889
  CollapsibleSection,
7840
8890
  {
@@ -7890,7 +8940,7 @@ function SaveButton({
7890
8940
  className
7891
8941
  }) {
7892
8942
  const { query } = useEditor();
7893
- const [saving, setSaving] = useState28(false);
8943
+ const [saving, setSaving] = useState29(false);
7894
8944
  const handleSave = async () => {
7895
8945
  setSaving(true);
7896
8946
  try {
@@ -7962,21 +9012,21 @@ function SaveButton({
7962
9012
  );
7963
9013
  }
7964
9014
  function PageBuilderPage({ pageId }) {
7965
- const { theme } = useContext4(AdminConfigContext);
7966
- const router = useRouter9();
7967
- const [title, setTitle] = useState28("");
7968
- const [slug, setSlug] = useState28("");
7969
- const [published, setPublished] = useState28(false);
7970
- const [initialContent, setInitialContent] = useState28(null);
7971
- const [loading, setLoading] = useState28(!!pageId);
7972
- const [rightTab, setRightTab] = useState28("designer");
7973
- const [seoTitle, setSeoTitle] = useState28("");
7974
- const [seoDescription, setSeoDescription] = useState28("");
7975
- const [seoKeywords, setSeoKeywords] = useState28("");
7976
- const [seoOgTitle, setSeoOgTitle] = useState28("");
7977
- const [seoOgDescription, setSeoOgDescription] = useState28("");
7978
- const [seoOgImage, setSeoOgImage] = useState28("");
7979
- const [pageSeoId, setPageSeoId] = useState28(null);
9015
+ const { theme } = useContext5(AdminConfigContext);
9016
+ const router = useRouter11();
9017
+ const [title, setTitle] = useState29("");
9018
+ const [slug, setSlug] = useState29("");
9019
+ const [published, setPublished] = useState29(false);
9020
+ const [initialContent, setInitialContent] = useState29(null);
9021
+ const [loading, setLoading] = useState29(!!pageId);
9022
+ const [rightTab, setRightTab] = useState29("designer");
9023
+ const [seoTitle, setSeoTitle] = useState29("");
9024
+ const [seoDescription, setSeoDescription] = useState29("");
9025
+ const [seoKeywords, setSeoKeywords] = useState29("");
9026
+ const [seoOgTitle, setSeoOgTitle] = useState29("");
9027
+ const [seoOgDescription, setSeoOgDescription] = useState29("");
9028
+ const [seoOgImage, setSeoOgImage] = useState29("");
9029
+ const [pageSeoId, setPageSeoId] = useState29(null);
7980
9030
  useEffect26(() => {
7981
9031
  if (!pageId) {
7982
9032
  setInitialContent(null);
@@ -8051,19 +9101,49 @@ function PageBuilderPage({ pageId }) {
8051
9101
  onSaved: (id) => {
8052
9102
  if (!pageId) router.replace(`/admin/pages/${id}`);
8053
9103
  },
8054
- className: "flex items-center bg-white text-gray-800 hover:bg-gray-100 border-0 text-xs",
9104
+ className: "md:hidden h-8 w-8 p-0 bg-white text-gray-800 hover:bg-gray-100 border-0",
9105
+ children: [
9106
+ /* @__PURE__ */ jsx54(Save4, { className: "h-4 w-4" }),
9107
+ /* @__PURE__ */ jsx54("span", { className: "sr-only", children: "Save" })
9108
+ ]
9109
+ }
9110
+ ),
9111
+ /* @__PURE__ */ jsxs45(
9112
+ SaveButton,
9113
+ {
9114
+ pageId,
9115
+ existingSeoId: pageSeoId,
9116
+ onSeoIdChange: setPageSeoId,
9117
+ pageData: { title, slug, published, seoTitle, seoDescription, seoKeywords, seoOgTitle, seoOgDescription, seoOgImage },
9118
+ onSaved: (id) => {
9119
+ if (!pageId) router.replace(`/admin/pages/${id}`);
9120
+ },
9121
+ className: "hidden md:inline-flex items-center bg-white text-gray-800 hover:bg-gray-100 border-0 text-xs",
8055
9122
  children: [
8056
9123
  /* @__PURE__ */ jsx54(Save4, { className: "h-4 w-4 mr-1" }),
8057
9124
  " Save"
8058
9125
  ]
8059
9126
  }
8060
9127
  ),
9128
+ /* @__PURE__ */ jsxs45(
9129
+ Button,
9130
+ {
9131
+ variant: "outline",
9132
+ size: "icon",
9133
+ className: "md:hidden h-8 w-8 bg-white text-gray-800 hover:bg-gray-100 border-0",
9134
+ onClick: () => router.push("/admin/pages"),
9135
+ children: [
9136
+ /* @__PURE__ */ jsx54(X17, { className: "h-4 w-4" }),
9137
+ /* @__PURE__ */ jsx54("span", { className: "sr-only", children: "Close" })
9138
+ ]
9139
+ }
9140
+ ),
8061
9141
  /* @__PURE__ */ jsxs45(
8062
9142
  Button,
8063
9143
  {
8064
9144
  variant: "outline",
8065
9145
  size: "sm",
8066
- className: "flex items-center bg-white text-gray-800 hover:bg-gray-100 border-0 text-xs",
9146
+ className: "hidden md:inline-flex items-center bg-white text-gray-800 hover:bg-gray-100 border-0 text-xs",
8067
9147
  onClick: () => router.push("/admin/pages"),
8068
9148
  children: [
8069
9149
  /* @__PURE__ */ jsx54(X17, { className: "h-4 w-4 mr-1" }),
@@ -8124,7 +9204,7 @@ function PageBuilderPage({ pageId }) {
8124
9204
  }
8125
9205
 
8126
9206
  // src/admin/pages/PluginsPage.tsx
8127
- import { useContext as useContext5, useState as useState29, useEffect as useEffect27 } from "react";
9207
+ import { useContext as useContext6, useState as useState30, useEffect as useEffect27 } from "react";
8128
9208
  import { HardDrive, Mail, CreditCard as CreditCard2, MessageCircle, BarChart3 as BarChart32, Building2 as Building22, Puzzle as Puzzle2, CheckCircle2 as CheckCircle22, XCircle, Save as Save5, X as X18, Plus as Plus8, Smartphone } from "lucide-react";
8129
9209
 
8130
9210
  // src/lib/email-recipients.ts
@@ -8149,7 +9229,7 @@ function serializeEmailRecipients(emails) {
8149
9229
  // src/components/ui/checkbox.tsx
8150
9230
  import * as React19 from "react";
8151
9231
  import * as CheckboxPrimitive from "@radix-ui/react-checkbox";
8152
- import { Check as Check6 } from "lucide-react";
9232
+ import { Check as Check7 } from "lucide-react";
8153
9233
  import { jsx as jsx55 } from "react/jsx-runtime";
8154
9234
  var Checkbox = React19.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx55(
8155
9235
  CheckboxPrimitive.Root,
@@ -8164,7 +9244,7 @@ var Checkbox = React19.forwardRef(({ className, ...props }, ref) => /* @__PURE__
8164
9244
  CheckboxPrimitive.Indicator,
8165
9245
  {
8166
9246
  className: cn("flex items-center justify-center text-current"),
8167
- children: /* @__PURE__ */ jsx55(Check6, { className: "h-4 w-4" })
9247
+ children: /* @__PURE__ */ jsx55(Check7, { className: "h-4 w-4" })
8168
9248
  }
8169
9249
  )
8170
9250
  }
@@ -8172,8 +9252,8 @@ var Checkbox = React19.forwardRef(({ className, ...props }, ref) => /* @__PURE__
8172
9252
  Checkbox.displayName = CheckboxPrimitive.Root.displayName;
8173
9253
 
8174
9254
  // src/admin/pages/PluginsPage.tsx
8175
- import { toast as toast4 } from "sonner";
8176
- import { Fragment as Fragment12, jsx as jsx56, jsxs as jsxs46 } from "react/jsx-runtime";
9255
+ import { toast as toast5 } from "sonner";
9256
+ import { Fragment as Fragment14, jsx as jsx56, jsxs as jsxs46 } from "react/jsx-runtime";
8177
9257
  function normalizeChatMode(raw) {
8178
9258
  if (raw === "external" || raw === "llm") return raw;
8179
9259
  return "whatsapp";
@@ -8238,7 +9318,7 @@ function EmailRecipientTags({
8238
9318
  onChange,
8239
9319
  placeholder
8240
9320
  }) {
8241
- const [draft, setDraft] = useState29("");
9321
+ const [draft, setDraft] = useState30("");
8242
9322
  const commitDraft = () => {
8243
9323
  const parts = splitInputToEmails(draft);
8244
9324
  if (!parts.length) return;
@@ -8314,35 +9394,35 @@ function PluginSettingsPanel({
8314
9394
  const isEmail = settingsGroup === "email";
8315
9395
  const isErp = settingsGroup === "erp";
8316
9396
  const isSms = settingsGroup === "sms";
8317
- const [enabled, setEnabled] = useState29(true);
8318
- const [botName, setBotName] = useState29("");
8319
- const [icon, setIcon] = useState29("");
8320
- const [iconImageUrl, setIconImageUrl] = useState29("");
8321
- const [iconBackgroundColor, setIconBackgroundColor] = useState29("#6366f1");
8322
- const [headerColor, setHeaderColor] = useState29("#6366f1");
8323
- const [salesTeamEmails, setSalesTeamEmails] = useState29([]);
8324
- const [fulfilmentTeamEmails, setFulfilmentTeamEmails] = useState29([]);
8325
- const [crmEmails, setCrmEmails] = useState29([]);
8326
- const [logoUrl, setLogoUrl] = useState29("");
8327
- const [companyName, setCompanyName] = useState29("");
8328
- const [supportEmail, setSupportEmail] = useState29("");
8329
- const [supportPhone, setSupportPhone] = useState29("");
8330
- const [followUsTitle, setFollowUsTitle] = useState29("Follow Us");
8331
- const [socialLinkRows, setSocialLinkRows] = useState29([{ ...EMPTY_SOCIAL_ROW }]);
8332
- const [footerDisclaimer, setFooterDisclaimer] = useState29("");
8333
- const [chatMode, setChatMode] = useState29("whatsapp");
8334
- const [whatsappPhone, setWhatsappPhone] = useState29("");
8335
- const [externalChatSnippet, setExternalChatSnippet] = useState29("");
8336
- const [erpPipelineName, setErpPipelineName] = useState29("");
8337
- const [erpPipelineStageName, setErpPipelineStageName] = useState29("");
8338
- const [erpFormsCatalog, setErpFormsCatalog] = useState29([]);
8339
- const [erpOpportunityFormIds, setErpOpportunityFormIds] = useState29([]);
8340
- const [erpOpportunityIdsKeyPresent, setErpOpportunityIdsKeyPresent] = useState29(false);
8341
- const [smsProviderChoice, setSmsProviderChoice] = useState29("auto");
8342
- const [msg91ApiMode, setMsg91ApiMode] = useState29("auto");
8343
- const [smsTplItems, setSmsTplItems] = useState29([]);
8344
- const [loading, setLoading] = useState29(true);
8345
- const [saving, setSaving] = useState29(false);
9397
+ const [enabled, setEnabled] = useState30(true);
9398
+ const [botName, setBotName] = useState30("");
9399
+ const [icon, setIcon] = useState30("");
9400
+ const [iconImageUrl, setIconImageUrl] = useState30("");
9401
+ const [iconBackgroundColor, setIconBackgroundColor] = useState30("#6366f1");
9402
+ const [headerColor, setHeaderColor] = useState30("#6366f1");
9403
+ const [salesTeamEmails, setSalesTeamEmails] = useState30([]);
9404
+ const [fulfilmentTeamEmails, setFulfilmentTeamEmails] = useState30([]);
9405
+ const [crmEmails, setCrmEmails] = useState30([]);
9406
+ const [logoUrl, setLogoUrl] = useState30("");
9407
+ const [companyName, setCompanyName] = useState30("");
9408
+ const [supportEmail, setSupportEmail] = useState30("");
9409
+ const [supportPhone, setSupportPhone] = useState30("");
9410
+ const [followUsTitle, setFollowUsTitle] = useState30("Follow Us");
9411
+ const [socialLinkRows, setSocialLinkRows] = useState30([{ ...EMPTY_SOCIAL_ROW }]);
9412
+ const [footerDisclaimer, setFooterDisclaimer] = useState30("");
9413
+ const [chatMode, setChatMode] = useState30("whatsapp");
9414
+ const [whatsappPhone, setWhatsappPhone] = useState30("");
9415
+ const [externalChatSnippet, setExternalChatSnippet] = useState30("");
9416
+ const [erpPipelineName, setErpPipelineName] = useState30("");
9417
+ const [erpPipelineStageName, setErpPipelineStageName] = useState30("");
9418
+ const [erpFormsCatalog, setErpFormsCatalog] = useState30([]);
9419
+ const [erpOpportunityFormIds, setErpOpportunityFormIds] = useState30([]);
9420
+ const [erpOpportunityIdsKeyPresent, setErpOpportunityIdsKeyPresent] = useState30(false);
9421
+ const [smsProviderChoice, setSmsProviderChoice] = useState30("auto");
9422
+ const [msg91ApiMode, setMsg91ApiMode] = useState30("auto");
9423
+ const [smsTplItems, setSmsTplItems] = useState30([]);
9424
+ const [loading, setLoading] = useState30(true);
9425
+ const [saving, setSaving] = useState30(false);
8346
9426
  useEffect27(() => {
8347
9427
  setLoading(true);
8348
9428
  fetch(`/api/settings/${settingsGroup}`).then((r) => r.ok ? r.json() : {}).then(async (data) => {
@@ -8484,10 +9564,10 @@ function PluginSettingsPanel({
8484
9564
  });
8485
9565
  if (!res2.ok) throw new Error();
8486
9566
  }
8487
- toast4.success("Settings saved");
9567
+ toast5.success("Settings saved");
8488
9568
  onSaved?.();
8489
9569
  } catch {
8490
- toast4.error("Failed to save");
9570
+ toast5.error("Failed to save");
8491
9571
  } finally {
8492
9572
  setSaving(false);
8493
9573
  }
@@ -8932,7 +10012,7 @@ function PluginSettingsPanel({
8932
10012
  ),
8933
10013
  /* @__PURE__ */ jsx56("p", { className: "text-xs text-gray-500 dark:text-gray-400", children: "Only paste code from sources you trust." })
8934
10014
  ] }),
8935
- chatMode === "llm" && /* @__PURE__ */ jsxs46(Fragment12, { children: [
10015
+ chatMode === "llm" && /* @__PURE__ */ jsxs46(Fragment14, { children: [
8936
10016
  /* @__PURE__ */ jsxs46("div", { className: "space-y-1", children: [
8937
10017
  /* @__PURE__ */ jsx56(Label3, { htmlFor: `${settingsGroup}-botName`, className: "text-sm", children: "Name" }),
8938
10018
  /* @__PURE__ */ jsx56(
@@ -9103,9 +10183,9 @@ function PluginListItem({
9103
10183
  );
9104
10184
  }
9105
10185
  function PluginsPage() {
9106
- const { pluginDescriptors = [] } = useContext5(AdminConfigContext);
9107
- const [selectedName, setSelectedName] = useState29(null);
9108
- const [enabledMap, setEnabledMap] = useState29({});
10186
+ const { pluginDescriptors = [] } = useContext6(AdminConfigContext);
10187
+ const [selectedName, setSelectedName] = useState30(null);
10188
+ const [enabledMap, setEnabledMap] = useState30({});
9109
10189
  useEffect27(() => {
9110
10190
  pluginDescriptors.forEach((p) => {
9111
10191
  if (!p.settingsGroup) return;
@@ -9146,7 +10226,7 @@ function PluginsPage() {
9146
10226
  /* @__PURE__ */ jsx56("div", { className: "min-w-0 flex-1", children: !selectedName ? /* @__PURE__ */ jsxs46("div", { className: "flex flex-col items-center justify-center py-12 text-center", children: [
9147
10227
  /* @__PURE__ */ jsx56(Puzzle2, { className: "h-10 w-10 text-gray-300 dark:text-gray-600" }),
9148
10228
  /* @__PURE__ */ jsx56("p", { className: "mt-3 text-sm text-gray-500 dark:text-gray-400", children: "Select a plugin to view or edit its configuration." })
9149
- ] }) : /* @__PURE__ */ jsx56("div", { className: "rounded-lg border border-gray-200 bg-gray-50/50 p-5 dark:border-gray-700 dark:bg-gray-800/50", children: selectedDescriptor?.settingsGroup ? /* @__PURE__ */ jsxs46(Fragment12, { children: [
10229
+ ] }) : /* @__PURE__ */ jsx56("div", { className: "rounded-lg border border-gray-200 bg-gray-50/50 p-5 dark:border-gray-700 dark:bg-gray-800/50", children: selectedDescriptor?.settingsGroup ? /* @__PURE__ */ jsxs46(Fragment14, { children: [
9150
10230
  /* @__PURE__ */ jsxs46("h2", { className: "text-sm font-medium text-gray-700 dark:text-gray-300 mb-4", children: [
9151
10231
  selectedDescriptor.label || selectedDescriptor.name,
9152
10232
  " \u2014 Configuration"
@@ -9167,9 +10247,9 @@ function PluginsPage() {
9167
10247
  }
9168
10248
 
9169
10249
  // src/admin/pages/BrandEditPage.tsx
9170
- import { useState as useState30, useEffect as useEffect28 } from "react";
9171
- import { useRouter as useRouter10 } from "next/navigation";
9172
- import { AlertCircle as AlertCircle4 } from "lucide-react";
10250
+ import { useState as useState31, useEffect as useEffect28 } from "react";
10251
+ import { useRouter as useRouter12 } from "next/navigation";
10252
+ import { AlertCircle as AlertCircle4, Save as Save6, Power } from "lucide-react";
9173
10253
 
9174
10254
  // src/components/Admin/SeoSection.tsx
9175
10255
  import { jsx as jsx57, jsxs as jsxs47 } from "react/jsx-runtime";
@@ -9260,22 +10340,22 @@ async function fetchSeo(seoId) {
9260
10340
  }
9261
10341
 
9262
10342
  // src/admin/pages/BrandEditPage.tsx
9263
- import { Fragment as Fragment13, jsx as jsx58, jsxs as jsxs48 } from "react/jsx-runtime";
10343
+ import { Fragment as Fragment15, jsx as jsx58, jsxs as jsxs48 } from "react/jsx-runtime";
9264
10344
  var isCreate = (id) => id === "create";
9265
10345
  function BrandEditPage({ brandId }) {
9266
- const router = useRouter10();
10346
+ const router = useRouter12();
9267
10347
  const create = isCreate(brandId);
9268
- const [loading, setLoading] = useState30(!create);
9269
- const [saving, setSaving] = useState30(false);
9270
- const [errors, setErrors] = useState30([]);
9271
- const [name, setName] = useState30("");
9272
- const [slug, setSlug] = useState30("");
9273
- const [description, setDescription] = useState30("");
9274
- const [logo, setLogo] = useState30("");
9275
- const [active, setActive] = useState30(true);
9276
- const [sortOrder, setSortOrder] = useState30(0);
9277
- const [seoId, setSeoId] = useState30(null);
9278
- const [seo, setSeo] = useState30({ seoTitle: "", seoDescription: "", seoKeywords: "", seoOgTitle: "", seoOgDescription: "", seoOgImage: "" });
10348
+ const [loading, setLoading] = useState31(!create);
10349
+ const [saving, setSaving] = useState31(false);
10350
+ const [errors, setErrors] = useState31([]);
10351
+ const [name, setName] = useState31("");
10352
+ const [slug, setSlug] = useState31("");
10353
+ const [description, setDescription] = useState31("");
10354
+ const [logo, setLogo] = useState31("");
10355
+ const [active, setActive] = useState31(true);
10356
+ const [sortOrder, setSortOrder] = useState31(0);
10357
+ const [seoId, setSeoId] = useState31(null);
10358
+ const [seo, setSeo] = useState31({ seoTitle: "", seoDescription: "", seoKeywords: "", seoOgTitle: "", seoOgDescription: "", seoOgImage: "" });
9279
10359
  useEffect28(() => {
9280
10360
  if (create) return;
9281
10361
  let cancelled = false;
@@ -9356,8 +10436,8 @@ function BrandEditPage({ brandId }) {
9356
10436
  subtitle: create ? "Create a new brand" : "Update brand details",
9357
10437
  closeHref: "/admin/brands",
9358
10438
  menuItems: [
9359
- { label: saving ? "Saving..." : "Save", onClick: handleSave },
9360
- { label: active ? "Deactivate" : "Activate", onClick: () => setActive(!active) }
10439
+ { label: saving ? "Saving..." : "Save", icon: Save6, onClick: handleSave },
10440
+ { label: active ? "Deactivate" : "Activate", icon: Power, onClick: () => setActive(!active) }
9361
10441
  ]
9362
10442
  }
9363
10443
  ),
@@ -9371,7 +10451,7 @@ function BrandEditPage({ brandId }) {
9371
10451
  /* @__PURE__ */ jsx58(
9372
10452
  DetailPageLayout,
9373
10453
  {
9374
- main: /* @__PURE__ */ jsxs48(Fragment13, { children: [
10454
+ main: /* @__PURE__ */ jsxs48(Fragment15, { children: [
9375
10455
  /* @__PURE__ */ jsxs48("section", { children: [
9376
10456
  /* @__PURE__ */ jsx58("h2", { className: "text-xs font-semibold text-gray-400 uppercase tracking-wider mb-2", children: "Basic info" }),
9377
10457
  /* @__PURE__ */ jsxs48("div", { className: "min-w-0 overflow-hidden border border-gray-200 rounded-lg p-4 bg-gray-50/50 space-y-4", children: [
@@ -9444,7 +10524,7 @@ function BrandEditPage({ brandId }) {
9444
10524
  /* @__PURE__ */ jsx58("div", { className: "min-w-0 overflow-hidden border border-gray-200 rounded-lg p-4 bg-gray-50/50", children: /* @__PURE__ */ jsx58(SeoSection, { values: seo, onChange: (field, value) => setSeo((s) => ({ ...s, [field]: value })) }) })
9445
10525
  ] })
9446
10526
  ] }),
9447
- sidebar: /* @__PURE__ */ jsx58(Fragment13, { children: /* @__PURE__ */ jsxs48("section", { children: [
10527
+ sidebar: /* @__PURE__ */ jsx58(Fragment15, { children: /* @__PURE__ */ jsxs48("section", { children: [
9448
10528
  /* @__PURE__ */ jsx58("h2", { className: "text-xs font-semibold text-gray-400 uppercase tracking-wider mb-2", children: "Status" }),
9449
10529
  /* @__PURE__ */ jsx58("div", { className: "min-w-0 overflow-hidden border border-gray-200 rounded-lg p-4 bg-gray-50/50", children: /* @__PURE__ */ jsxs48("label", { className: "flex items-center gap-2 cursor-pointer", children: [
9450
10530
  /* @__PURE__ */ jsx58(
@@ -9465,12 +10545,12 @@ function BrandEditPage({ brandId }) {
9465
10545
  }
9466
10546
 
9467
10547
  // src/admin/pages/ProductEditPage.tsx
9468
- import { useState as useState32, useEffect as useEffect30 } from "react";
9469
- import { useRouter as useRouter11 } from "next/navigation";
9470
- import { AlertCircle as AlertCircle5, Plus as Plus9, Trash2 as Trash25, Star } from "lucide-react";
10548
+ import { useState as useState33, useEffect as useEffect30 } from "react";
10549
+ import { useRouter as useRouter13 } from "next/navigation";
10550
+ import { AlertCircle as AlertCircle5, Plus as Plus9, Trash2 as Trash25, Star, Save as Save7 } from "lucide-react";
9471
10551
 
9472
10552
  // src/components/Admin/AttributeFacetNameInput.tsx
9473
- import { useState as useState31, useEffect as useEffect29 } from "react";
10553
+ import { useState as useState32, useEffect as useEffect29, useRef as useRef11 } from "react";
9474
10554
  import { jsx as jsx59, jsxs as jsxs49 } from "react/jsx-runtime";
9475
10555
  function slugFromName(name) {
9476
10556
  const s = name.toLowerCase().trim().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "");
@@ -9481,12 +10561,15 @@ function AttributeFacetNameInput({
9481
10561
  onChange,
9482
10562
  inputClassName
9483
10563
  }) {
9484
- const [draft, setDraft] = useState31(value);
9485
- const [open, setOpen] = useState31(false);
9486
- const [list, setList] = useState31([]);
10564
+ const [draft, setDraft] = useState32(value);
10565
+ const [open, setOpen] = useState32(false);
10566
+ const [list, setList] = useState32([]);
10567
+ const isFocusedRef = useRef11(false);
9487
10568
  useEffect29(() => {
9488
- setDraft(value);
9489
- }, [value]);
10569
+ if (!isFocusedRef.current && value !== draft) {
10570
+ setDraft(value);
10571
+ }
10572
+ }, [value, draft]);
9490
10573
  useEffect29(() => {
9491
10574
  const q = draft.trim();
9492
10575
  if (!q) {
@@ -9549,8 +10632,12 @@ function AttributeFacetNameInput({
9549
10632
  setDraft(e.target.value);
9550
10633
  setOpen(true);
9551
10634
  },
9552
- onFocus: () => setOpen(true),
10635
+ onFocus: () => {
10636
+ setOpen(true);
10637
+ isFocusedRef.current = true;
10638
+ },
9553
10639
  onBlur: () => setTimeout(() => {
10640
+ isFocusedRef.current = false;
9554
10641
  setOpen(false);
9555
10642
  onChange(draft.trim());
9556
10643
  }, 200),
@@ -9604,7 +10691,7 @@ function AttributeFacetNameInput({
9604
10691
  }
9605
10692
 
9606
10693
  // src/admin/pages/ProductEditPage.tsx
9607
- import { Fragment as Fragment14, jsx as jsx60, jsxs as jsxs50 } from "react/jsx-runtime";
10694
+ import { Fragment as Fragment16, jsx as jsx60, jsxs as jsxs50 } from "react/jsx-runtime";
9608
10695
  var isCreate2 = (id) => id === "create";
9609
10696
  var sectionCls = "min-w-0 overflow-hidden border border-gray-200 rounded-lg p-4 bg-gray-50/50";
9610
10697
  var labelCls = "block text-xs font-medium text-gray-600 mb-1";
@@ -9638,33 +10725,37 @@ function pickOtherMetadata(m) {
9638
10725
  return rest;
9639
10726
  }
9640
10727
  function ProductEditPage({ productId }) {
9641
- const router = useRouter11();
10728
+ const router = useRouter13();
9642
10729
  const create = isCreate2(productId);
9643
- const [loading, setLoading] = useState32(!create);
9644
- const [saving, setSaving] = useState32(false);
9645
- const [errors, setErrors] = useState32([]);
9646
- const [collections, setCollections] = useState32([]);
9647
- const [brands, setBrands] = useState32([]);
9648
- const [categories, setCategories] = useState32([]);
9649
- const [name, setName] = useState32("");
9650
- const [productSlug, setProductSlug] = useState32("");
9651
- const [sku, setSku] = useState32("");
9652
- const [hsn, setHsn] = useState32("");
9653
- const [collectionId, setCollectionId] = useState32(null);
9654
- const [brandId, setBrandId] = useState32(null);
9655
- const [categoryId, setCategoryId] = useState32(null);
9656
- const [price, setPrice] = useState32("");
9657
- const [compareAtPrice, setCompareAtPrice] = useState32("");
9658
- const [quantity, setQuantity] = useState32(1);
9659
- const [status, setStatus] = useState32("draft");
9660
- const [featured, setFeatured] = useState32(false);
9661
- const [description, setDescription] = useState32("");
9662
- const [images, setImages] = useState32([{ url: "", alt: "", isDefault: true }]);
9663
- const [specifications, setSpecifications] = useState32([{ key: "", value: "" }]);
9664
- const [otherMetadata, setOtherMetadata] = useState32({});
9665
- const [facetRows, setFacetRows] = useState32([{ name: "", value: "" }]);
9666
- const [seoId, setSeoId] = useState32(null);
9667
- const [seo, setSeo] = useState32({
10730
+ const [loading, setLoading] = useState33(!create);
10731
+ const [saving, setSaving] = useState33(false);
10732
+ const [errors, setErrors] = useState33([]);
10733
+ const [collections, setCollections] = useState33([]);
10734
+ const [brands, setBrands] = useState33([]);
10735
+ const [categories, setCategories] = useState33([]);
10736
+ const [name, setName] = useState33("");
10737
+ const [productSlug, setProductSlug] = useState33("");
10738
+ const [sku, setSku] = useState33("");
10739
+ const [hsn, setHsn] = useState33("");
10740
+ const [uom, setUom] = useState33("");
10741
+ const [productType, setProductType] = useState33("product");
10742
+ const [collectionId, setCollectionId] = useState33(null);
10743
+ const [brandId, setBrandId] = useState33(null);
10744
+ const [categoryId, setCategoryId] = useState33(null);
10745
+ const [price, setPrice] = useState33("");
10746
+ const [compareAtPrice, setCompareAtPrice] = useState33("");
10747
+ const [quantity, setQuantity] = useState33(1);
10748
+ const [status, setStatus] = useState33("draft");
10749
+ const [featured, setFeatured] = useState33(false);
10750
+ const [description, setDescription] = useState33("");
10751
+ const [images, setImages] = useState33([{ url: "", alt: "", isDefault: true }]);
10752
+ const [specifications, setSpecifications] = useState33([{ key: "", value: "" }]);
10753
+ const [otherMetadata, setOtherMetadata] = useState33({});
10754
+ const [facetRows, setFacetRows] = useState33([{ name: "", value: "" }]);
10755
+ const [taxMasterList, setTaxMasterList] = useState33([]);
10756
+ const [taxRows, setTaxRows] = useState33([{ taxId: "", rate: "" }]);
10757
+ const [seoId, setSeoId] = useState33(null);
10758
+ const [seo, setSeo] = useState33({
9668
10759
  seoTitle: "",
9669
10760
  seoDescription: "",
9670
10761
  seoKeywords: "",
@@ -9676,11 +10767,12 @@ function ProductEditPage({ productId }) {
9676
10767
  let cancelled = false;
9677
10768
  (async () => {
9678
10769
  try {
9679
- const [colRes, brandRes, catRes, attrRes] = await Promise.all([
10770
+ const [colRes, brandRes, catRes, attrRes, taxesRes] = await Promise.all([
9680
10771
  fetch("/api/collections?limit=500"),
9681
10772
  fetch("/api/brands?limit=500"),
9682
10773
  fetch("/api/product_categories?limit=500"),
9683
- fetch("/api/attributes?limit=500")
10774
+ fetch("/api/attributes?limit=500"),
10775
+ fetch("/api/taxes?limit=200&sortField=name&sortOrder=asc")
9684
10776
  ]);
9685
10777
  let attrList = [];
9686
10778
  if (!cancelled && colRes.ok) {
@@ -9699,6 +10791,13 @@ function ProductEditPage({ productId }) {
9699
10791
  const d = await attrRes.json();
9700
10792
  if (Array.isArray(d.data)) attrList = d.data;
9701
10793
  }
10794
+ if (!cancelled && taxesRes.ok) {
10795
+ const d = await taxesRes.json();
10796
+ const raw = Array.isArray(d.data) ? d.data : [];
10797
+ setTaxMasterList(
10798
+ raw.filter((t) => t.active !== false && t.deleted !== true)
10799
+ );
10800
+ }
9702
10801
  if (create) {
9703
10802
  if (!cancelled) {
9704
10803
  setProductSlug("");
@@ -9714,6 +10813,8 @@ function ProductEditPage({ productId }) {
9714
10813
  setProductSlug(typeof product.slug === "string" ? product.slug : "");
9715
10814
  setSku(product.sku ?? "");
9716
10815
  setHsn(product.hsn ?? "");
10816
+ setUom(product.uom != null ? String(product.uom) : "");
10817
+ setProductType(product.type === "service" ? "service" : "product");
9717
10818
  setCollectionId(product.collectionId ?? null);
9718
10819
  setBrandId(product.brandId ?? null);
9719
10820
  setCategoryId(product.categoryId ?? null);
@@ -9744,6 +10845,19 @@ function ProductEditPage({ productId }) {
9744
10845
  const seoData = await fetchSeo(product.seoId);
9745
10846
  if (!cancelled) setSeo(seoData);
9746
10847
  }
10848
+ const ptRes = await fetch(`/api/product_taxes?productId=${productId}&limit=100`);
10849
+ if (ptRes.ok && !cancelled) {
10850
+ const ptData = await ptRes.json();
10851
+ const pts = Array.isArray(ptData.data) ? ptData.data : [];
10852
+ if (pts.length > 0) {
10853
+ setTaxRows(
10854
+ pts.map((p) => ({
10855
+ taxId: p.taxId,
10856
+ rate: p.rate != null && p.rate !== "" ? String(p.rate) : ""
10857
+ }))
10858
+ );
10859
+ } else if (!cancelled) setTaxRows([{ taxId: "", rate: "" }]);
10860
+ }
9747
10861
  const paRes = await fetch(`/api/product_attributes?productId=${productId}&limit=100`);
9748
10862
  if (paRes.ok && !cancelled) {
9749
10863
  const paData = await paRes.json();
@@ -9792,6 +10906,8 @@ function ProductEditPage({ productId }) {
9792
10906
  name: name.trim(),
9793
10907
  sku: sku.trim() || null,
9794
10908
  hsn: hsn.trim() || null,
10909
+ uom: uom.trim() || null,
10910
+ type: productType,
9795
10911
  collectionId: collectionId || null,
9796
10912
  brandId: brandId || null,
9797
10913
  categoryId: categoryId || null,
@@ -9888,6 +11004,55 @@ function ProductEditPage({ productId }) {
9888
11004
  });
9889
11005
  }
9890
11006
  }
11007
+ const parseTaxRate = (s) => {
11008
+ const t = s.trim();
11009
+ if (!t) return null;
11010
+ const n = Number(t);
11011
+ return Number.isFinite(n) ? n : null;
11012
+ };
11013
+ const ratesDiffer = (a, b) => {
11014
+ if (a == null && b == null) return false;
11015
+ if (a == null || b == null) return true;
11016
+ return Math.abs(a - b) > 1e-6;
11017
+ };
11018
+ const wantedTax = /* @__PURE__ */ new Map();
11019
+ for (const row of taxRows) {
11020
+ if (row.taxId === "") continue;
11021
+ wantedTax.set(row.taxId, parseTaxRate(row.rate));
11022
+ }
11023
+ const ptListRes = await fetch(`/api/product_taxes?productId=${savedId}&limit=200`);
11024
+ const ptListData = ptListRes.ok ? await ptListRes.json() : { data: [] };
11025
+ const existingPt = Array.isArray(ptListData.data) ? ptListData.data : [];
11026
+ for (const ep of existingPt) {
11027
+ if (!wantedTax.has(ep.taxId)) {
11028
+ await fetch(`/api/product_taxes/${ep.id}`, { method: "DELETE" });
11029
+ }
11030
+ }
11031
+ const survivors = existingPt.filter((ep) => wantedTax.has(ep.taxId));
11032
+ for (const [taxId, rate] of wantedTax) {
11033
+ const ep = survivors.find((e) => e.taxId === taxId);
11034
+ if (!ep) {
11035
+ await fetch("/api/product_taxes", {
11036
+ method: "POST",
11037
+ headers: { "Content-Type": "application/json" },
11038
+ body: JSON.stringify({
11039
+ productId: Number(savedId),
11040
+ taxId,
11041
+ rate
11042
+ })
11043
+ });
11044
+ } else {
11045
+ const existingRate = ep.rate == null || String(ep.rate).trim() === "" ? null : Number(ep.rate);
11046
+ const er = Number.isFinite(existingRate) ? existingRate : null;
11047
+ if (ratesDiffer(er, rate)) {
11048
+ await fetch(`/api/product_taxes/${ep.id}`, {
11049
+ method: "PUT",
11050
+ headers: { "Content-Type": "application/json" },
11051
+ body: JSON.stringify({ rate })
11052
+ });
11053
+ }
11054
+ }
11055
+ }
9891
11056
  router.push("/admin/products");
9892
11057
  } catch {
9893
11058
  setErrors(["Failed to save"]);
@@ -9905,6 +11070,18 @@ function ProductEditPage({ productId }) {
9905
11070
  const addFacet = () => setFacetRows((prev) => [...prev, { name: "", value: "" }]);
9906
11071
  const removeFacet = (i) => setFacetRows((prev) => prev.length <= 1 ? prev : prev.filter((_, j) => j !== i));
9907
11072
  const setFacet = (i, field, value) => setFacetRows((prev) => prev.map((row, j) => j === i ? { ...row, [field]: value } : row));
11073
+ const addTaxRow = () => setTaxRows((prev) => [...prev, { taxId: "", rate: "" }]);
11074
+ const removeTaxRow = (i) => setTaxRows((prev) => prev.length <= 1 ? prev : prev.filter((_, j) => j !== i));
11075
+ const setTaxRow = (i, patch) => setTaxRows((prev) => prev.map((row, j) => j === i ? { ...row, ...patch } : row));
11076
+ const taxesForSelect = (rowIndex) => {
11077
+ const row = taxRows[rowIndex];
11078
+ const selectedElsewhere = new Set(
11079
+ taxRows.map((r, j) => j !== rowIndex && r.taxId !== "" ? r.taxId : null).filter((x) => x != null)
11080
+ );
11081
+ return taxMasterList.filter(
11082
+ (t) => !selectedElsewhere.has(t.id) || row && row.taxId !== "" && t.id === row.taxId
11083
+ );
11084
+ };
9908
11085
  if (loading) {
9909
11086
  return /* @__PURE__ */ jsx60("div", { className: "flex items-center justify-center py-12", children: /* @__PURE__ */ jsx60("span", { className: "text-gray-500", children: "Loading..." }) });
9910
11087
  }
@@ -9916,8 +11093,8 @@ function ProductEditPage({ productId }) {
9916
11093
  subtitle: create ? "Create a new product" : "Update product details",
9917
11094
  closeHref: "/admin/products",
9918
11095
  menuItems: [
9919
- { label: saving ? "Saving..." : "Save", onClick: handleSave },
9920
- { label: featured ? "Unfeature" : "Feature", onClick: () => setFeatured(!featured) }
11096
+ { label: saving ? "Saving..." : "Save", icon: Save7, onClick: handleSave },
11097
+ { label: featured ? "Unfeature" : "Feature", icon: Star, onClick: () => setFeatured(!featured) }
9921
11098
  ]
9922
11099
  }
9923
11100
  ),
@@ -9931,7 +11108,7 @@ function ProductEditPage({ productId }) {
9931
11108
  /* @__PURE__ */ jsx60(
9932
11109
  DetailPageLayout,
9933
11110
  {
9934
- main: /* @__PURE__ */ jsxs50(Fragment14, { children: [
11111
+ main: /* @__PURE__ */ jsxs50(Fragment16, { children: [
9935
11112
  /* @__PURE__ */ jsxs50("section", { children: [
9936
11113
  /* @__PURE__ */ jsx60("h2", { className: "text-xs font-semibold text-gray-400 uppercase tracking-wider mb-2", children: "Product details" }),
9937
11114
  /* @__PURE__ */ jsxs50("div", { className: `${sectionCls} space-y-4`, children: [
@@ -9949,6 +11126,36 @@ function ProductEditPage({ productId }) {
9949
11126
  /* @__PURE__ */ jsx60("input", { type: "text", value: hsn, onChange: (e) => setHsn(e.target.value), className: inputCls })
9950
11127
  ] })
9951
11128
  ] }),
11129
+ /* @__PURE__ */ jsxs50("div", { className: "grid grid-cols-2 gap-4", children: [
11130
+ /* @__PURE__ */ jsxs50("div", { children: [
11131
+ /* @__PURE__ */ jsx60("label", { className: labelCls, children: "UOM" }),
11132
+ /* @__PURE__ */ jsx60(
11133
+ "input",
11134
+ {
11135
+ type: "text",
11136
+ value: uom,
11137
+ onChange: (e) => setUom(e.target.value),
11138
+ className: inputCls,
11139
+ placeholder: "e.g. pcs, kg, hrs"
11140
+ }
11141
+ )
11142
+ ] }),
11143
+ /* @__PURE__ */ jsxs50("div", { children: [
11144
+ /* @__PURE__ */ jsx60("label", { className: labelCls, children: "Product type" }),
11145
+ /* @__PURE__ */ jsxs50(
11146
+ "select",
11147
+ {
11148
+ value: productType,
11149
+ onChange: (e) => setProductType(e.target.value === "service" ? "service" : "product"),
11150
+ className: inputCls,
11151
+ children: [
11152
+ /* @__PURE__ */ jsx60("option", { value: "product", children: "Product" }),
11153
+ /* @__PURE__ */ jsx60("option", { value: "service", children: "Service" })
11154
+ ]
11155
+ }
11156
+ )
11157
+ ] })
11158
+ ] }),
9952
11159
  /* @__PURE__ */ jsxs50("div", { className: "grid grid-cols-2 gap-4", children: [
9953
11160
  /* @__PURE__ */ jsxs50("div", { children: [
9954
11161
  /* @__PURE__ */ jsx60("label", { className: labelCls, children: "Brand" }),
@@ -9999,6 +11206,78 @@ function ProductEditPage({ productId }) {
9999
11206
  ] })
10000
11207
  ] })
10001
11208
  ] }),
11209
+ /* @__PURE__ */ jsxs50("section", { children: [
11210
+ /* @__PURE__ */ jsx60("h2", { className: "text-xs font-semibold text-gray-400 uppercase tracking-wider mb-2", children: "Taxes" }),
11211
+ /* @__PURE__ */ jsx60("p", { className: "text-xs text-gray-500 mb-2", children: "Link taxes for this product. Leave rate empty to use the tax's default rate; set a value to override." }),
11212
+ /* @__PURE__ */ jsxs50("div", { className: `${sectionCls} space-y-2`, children: [
11213
+ taxRows.map((row, i) => {
11214
+ const options = taxesForSelect(i);
11215
+ const master = row.taxId !== "" ? taxMasterList.find((t) => t.id === row.taxId) : void 0;
11216
+ const defaultRateHint = master != null ? `Default: ${String(master.rate)}%` : void 0;
11217
+ return /* @__PURE__ */ jsxs50("div", { className: "flex flex-wrap gap-2 items-end", children: [
11218
+ /* @__PURE__ */ jsxs50("div", { className: "min-w-[160px] flex-1", children: [
11219
+ /* @__PURE__ */ jsx60("label", { className: labelCls, children: "Tax" }),
11220
+ /* @__PURE__ */ jsxs50(
11221
+ "select",
11222
+ {
11223
+ value: row.taxId === "" ? "" : String(row.taxId),
11224
+ onChange: (e) => {
11225
+ const v = e.target.value;
11226
+ setTaxRow(i, { taxId: v === "" ? "" : Number(v) });
11227
+ },
11228
+ className: inputCls,
11229
+ children: [
11230
+ /* @__PURE__ */ jsx60("option", { value: "", children: "\u2014" }),
11231
+ options.map((t) => /* @__PURE__ */ jsxs50("option", { value: t.id, children: [
11232
+ t.name,
11233
+ " (",
11234
+ String(t.rate),
11235
+ "%)"
11236
+ ] }, t.id))
11237
+ ]
11238
+ }
11239
+ )
11240
+ ] }),
11241
+ /* @__PURE__ */ jsxs50("div", { className: "w-28", children: [
11242
+ /* @__PURE__ */ jsx60("label", { className: labelCls, children: "Rate %" }),
11243
+ /* @__PURE__ */ jsx60(
11244
+ "input",
11245
+ {
11246
+ type: "text",
11247
+ inputMode: "decimal",
11248
+ value: row.rate,
11249
+ onChange: (e) => setTaxRow(i, { rate: e.target.value }),
11250
+ className: inputCls,
11251
+ placeholder: defaultRateHint ?? "optional",
11252
+ title: defaultRateHint
11253
+ }
11254
+ )
11255
+ ] }),
11256
+ /* @__PURE__ */ jsx60(
11257
+ "button",
11258
+ {
11259
+ type: "button",
11260
+ onClick: () => removeTaxRow(i),
11261
+ className: "p-2 text-gray-400 hover:text-red-600 rounded shrink-0 mb-0.5",
11262
+ children: /* @__PURE__ */ jsx60(Trash25, { className: "h-4 w-4" })
11263
+ }
11264
+ )
11265
+ ] }, i);
11266
+ }),
11267
+ /* @__PURE__ */ jsxs50(
11268
+ "button",
11269
+ {
11270
+ type: "button",
11271
+ onClick: addTaxRow,
11272
+ className: "inline-flex items-center gap-1 rounded border border-gray-300 bg-white px-2 py-1.5 text-xs font-medium text-gray-700 hover:bg-gray-50",
11273
+ children: [
11274
+ /* @__PURE__ */ jsx60(Plus9, { className: "h-3.5 w-3.5" }),
11275
+ " Add tax"
11276
+ ]
11277
+ }
11278
+ )
11279
+ ] })
11280
+ ] }),
10002
11281
  /* @__PURE__ */ jsxs50("section", { children: [
10003
11282
  /* @__PURE__ */ jsx60("h2", { className: "text-xs font-semibold text-gray-400 uppercase tracking-wider mb-2", children: "Attributes (facets)" }),
10004
11283
  /* @__PURE__ */ jsx60("p", { className: "text-xs text-gray-500 mb-2", children: "Search existing attributes or create new ones (like blog categories). Value on the right." }),
@@ -10133,10 +11412,10 @@ function ProductEditPage({ productId }) {
10133
11412
  }
10134
11413
 
10135
11414
  // src/admin/pages/CollectionEditPage.tsx
10136
- import { useState as useState33, useEffect as useEffect31 } from "react";
10137
- import { useRouter as useRouter12 } from "next/navigation";
10138
- import { AlertCircle as AlertCircle6, Plus as Plus10, Trash2 as Trash26, ChevronDown as ChevronDown6, ChevronUp as ChevronUp2 } from "lucide-react";
10139
- import { Fragment as Fragment15, jsx as jsx61, jsxs as jsxs51 } from "react/jsx-runtime";
11415
+ import { useState as useState34, useEffect as useEffect31 } from "react";
11416
+ import { useRouter as useRouter14 } from "next/navigation";
11417
+ import { AlertCircle as AlertCircle6, Plus as Plus10, Trash2 as Trash26, ChevronDown as ChevronDown6, ChevronUp as ChevronUp2, Save as Save8, Power as Power2 } from "lucide-react";
11418
+ import { Fragment as Fragment17, jsx as jsx61, jsxs as jsxs51 } from "react/jsx-runtime";
10140
11419
  var isCreate3 = (id) => id === "create";
10141
11420
  var emptySlide = () => ({ url: "", type: "image", caption: "" });
10142
11421
  var emptyVariant = () => ({ name: "", price: "", extraSpecs: [] });
@@ -10144,29 +11423,29 @@ var sectionCls2 = "min-w-0 overflow-hidden border border-gray-200 rounded-lg p-4
10144
11423
  var labelCls2 = "block text-xs font-medium text-gray-600 mb-1";
10145
11424
  var inputCls2 = "w-full rounded-md border border-gray-300 px-2 py-1.5 text-sm";
10146
11425
  function CollectionEditPage({ collectionId }) {
10147
- const router = useRouter12();
11426
+ const router = useRouter14();
10148
11427
  const create = isCreate3(collectionId);
10149
- const [loading, setLoading] = useState33(!create);
10150
- const [saving, setSaving] = useState33(false);
10151
- const [errors, setErrors] = useState33([]);
10152
- const [categories, setCategories] = useState33([]);
10153
- const [brands, setBrands] = useState33([]);
10154
- const [name, setName] = useState33("");
10155
- const [slug, setSlug] = useState33("");
10156
- const [hsn, setHsn] = useState33("");
10157
- const [categoryId, setCategoryId] = useState33(null);
10158
- const [brandId, setBrandId] = useState33(null);
10159
- const [description, setDescription] = useState33("");
10160
- const [image, setImage] = useState33("");
10161
- const [active, setActive] = useState33(true);
10162
- const [sortOrder, setSortOrder] = useState33(0);
10163
- const [advancedOpen, setAdvancedOpen] = useState33(false);
10164
- const [heroSlides, setHeroSlides] = useState33([emptySlide()]);
10165
- const [variants, setVariants] = useState33([emptyVariant()]);
10166
- const [experienceDescription, setExperienceDescription] = useState33("");
10167
- const [brochureUrl, setBrochureUrl] = useState33("");
10168
- const [seoId, setSeoId] = useState33(null);
10169
- const [seo, setSeo] = useState33({
11428
+ const [loading, setLoading] = useState34(!create);
11429
+ const [saving, setSaving] = useState34(false);
11430
+ const [errors, setErrors] = useState34([]);
11431
+ const [categories, setCategories] = useState34([]);
11432
+ const [brands, setBrands] = useState34([]);
11433
+ const [name, setName] = useState34("");
11434
+ const [slug, setSlug] = useState34("");
11435
+ const [hsn, setHsn] = useState34("");
11436
+ const [categoryId, setCategoryId] = useState34(null);
11437
+ const [brandId, setBrandId] = useState34(null);
11438
+ const [description, setDescription] = useState34("");
11439
+ const [image, setImage] = useState34("");
11440
+ const [active, setActive] = useState34(true);
11441
+ const [sortOrder, setSortOrder] = useState34(0);
11442
+ const [advancedOpen, setAdvancedOpen] = useState34(false);
11443
+ const [heroSlides, setHeroSlides] = useState34([emptySlide()]);
11444
+ const [variants, setVariants] = useState34([emptyVariant()]);
11445
+ const [experienceDescription, setExperienceDescription] = useState34("");
11446
+ const [brochureUrl, setBrochureUrl] = useState34("");
11447
+ const [seoId, setSeoId] = useState34(null);
11448
+ const [seo, setSeo] = useState34({
10170
11449
  seoTitle: "",
10171
11450
  seoDescription: "",
10172
11451
  seoKeywords: "",
@@ -10347,8 +11626,8 @@ function CollectionEditPage({ collectionId }) {
10347
11626
  subtitle: create ? "Create a new collection" : "Update collection and page content",
10348
11627
  closeHref: "/admin/collections",
10349
11628
  menuItems: [
10350
- { label: saving ? "Saving..." : "Save", onClick: handleSave },
10351
- { label: active ? "Deactivate" : "Activate", onClick: () => setActive(!active) }
11629
+ { label: saving ? "Saving..." : "Save", icon: Save8, onClick: handleSave },
11630
+ { label: active ? "Deactivate" : "Activate", icon: Power2, onClick: () => setActive(!active) }
10352
11631
  ]
10353
11632
  }
10354
11633
  ),
@@ -10362,7 +11641,7 @@ function CollectionEditPage({ collectionId }) {
10362
11641
  /* @__PURE__ */ jsx61(
10363
11642
  DetailPageLayout,
10364
11643
  {
10365
- main: /* @__PURE__ */ jsxs51(Fragment15, { children: [
11644
+ main: /* @__PURE__ */ jsxs51(Fragment17, { children: [
10366
11645
  /* @__PURE__ */ jsxs51("section", { children: [
10367
11646
  /* @__PURE__ */ jsx61("h2", { className: "text-xs font-semibold text-gray-400 uppercase tracking-wider mb-2", children: "Basic info" }),
10368
11647
  /* @__PURE__ */ jsxs51("div", { className: `${sectionCls2} space-y-4`, children: [
@@ -10472,7 +11751,7 @@ function CollectionEditPage({ collectionId }) {
10472
11751
  ] })
10473
11752
  ] })
10474
11753
  ] }),
10475
- sidebar: /* @__PURE__ */ jsxs51(Fragment15, { children: [
11754
+ sidebar: /* @__PURE__ */ jsxs51(Fragment17, { children: [
10476
11755
  /* @__PURE__ */ jsxs51("section", { children: [
10477
11756
  /* @__PURE__ */ jsx61("h2", { className: "text-xs font-semibold text-gray-400 uppercase tracking-wider mb-2", children: "Status" }),
10478
11757
  /* @__PURE__ */ jsx61("div", { className: sectionCls2, children: /* @__PURE__ */ jsxs51("label", { className: "flex items-center gap-2 cursor-pointer", children: [
@@ -10491,9 +11770,9 @@ function CollectionEditPage({ collectionId }) {
10491
11770
  }
10492
11771
 
10493
11772
  // src/admin/pages/RolesPage.tsx
10494
- import { useCallback as useCallback7, useEffect as useEffect32, useState as useState34 } from "react";
11773
+ import { useCallback as useCallback7, useEffect as useEffect32, useState as useState35 } from "react";
10495
11774
  import { useSession as useSession5 } from "next-auth/react";
10496
- import { Shield as Shield2, Save as Save6, Trash2 as Trash27 } from "lucide-react";
11775
+ import { Shield as Shield2, Save as Save9, Trash2 as Trash27 } from "lucide-react";
10497
11776
 
10498
11777
  // src/auth/permission-entities.ts
10499
11778
  var ADMIN_GROUP_NAME = "Administrator";
@@ -10526,14 +11805,15 @@ function RolesPage() {
10526
11805
  const { data: session, status } = useSession5();
10527
11806
  const u = session?.user;
10528
11807
  const canManage = !!u?.isRBACAdmin;
10529
- const [entities, setEntities] = useState34([]);
10530
- const [groups, setGroups] = useState34([]);
10531
- const [selectedId, setSelectedId] = useState34(null);
10532
- const [matrix, setMatrix] = useState34({});
10533
- const [loading, setLoading] = useState34(true);
10534
- const [saving, setSaving] = useState34(false);
10535
- const [newName, setNewName] = useState34("");
10536
- const [error, setError] = useState34(null);
11808
+ const [entities, setEntities] = useState35([]);
11809
+ const [groups, setGroups] = useState35([]);
11810
+ const [selectedId, setSelectedId] = useState35(null);
11811
+ const [matrix, setMatrix] = useState35({});
11812
+ const [loading, setLoading] = useState35(true);
11813
+ const [saving, setSaving] = useState35(false);
11814
+ const [newName, setNewName] = useState35("");
11815
+ const [deleteRoleOpen, setDeleteRoleOpen] = useState35(false);
11816
+ const [error, setError] = useState35(null);
10537
11817
  const load = useCallback7(async () => {
10538
11818
  setLoading(true);
10539
11819
  setError(null);
@@ -10588,6 +11868,45 @@ function RolesPage() {
10588
11868
  [entity]: { ...prev[entity], [key]: !prev[entity][key] }
10589
11869
  }));
10590
11870
  };
11871
+ const PERM_KEYS = [
11872
+ "canCreate",
11873
+ "canRead",
11874
+ "canUpdate",
11875
+ "canDelete"
11876
+ ];
11877
+ const isColumnAllChecked = (key) => entities.length > 0 && entities.every((entity) => matrix[entity]?.[key]);
11878
+ const toggleColumn = (key) => {
11879
+ const nextValue = !isColumnAllChecked(key);
11880
+ setMatrix((prev) => {
11881
+ const next = { ...prev };
11882
+ for (const entity of entities) {
11883
+ if (!next[entity]) continue;
11884
+ next[entity] = { ...next[entity], [key]: nextValue };
11885
+ }
11886
+ return next;
11887
+ });
11888
+ };
11889
+ const isAllChecked = entities.length > 0 && entities.every((entity) => {
11890
+ const row = matrix[entity];
11891
+ return row ? PERM_KEYS.every((k) => row[k]) : false;
11892
+ });
11893
+ const toggleAll = () => {
11894
+ const nextValue = !isAllChecked;
11895
+ setMatrix((prev) => {
11896
+ const next = { ...prev };
11897
+ for (const entity of entities) {
11898
+ if (!next[entity]) continue;
11899
+ next[entity] = {
11900
+ ...next[entity],
11901
+ canCreate: nextValue,
11902
+ canRead: nextValue,
11903
+ canUpdate: nextValue,
11904
+ canDelete: nextValue
11905
+ };
11906
+ }
11907
+ return next;
11908
+ });
11909
+ };
10591
11910
  const saveMatrix = async () => {
10592
11911
  if (!selectedId) return;
10593
11912
  setSaving(true);
@@ -10636,7 +11955,6 @@ function RolesPage() {
10636
11955
  };
10637
11956
  const deleteGroup = async () => {
10638
11957
  if (!selectedId || !selected || isSuperAdminGroupName(selected.name)) return;
10639
- if (!confirm(`Delete group "${selected.name}"?`)) return;
10640
11958
  try {
10641
11959
  const res = await fetch(`/api/admin/roles/${selectedId}`, { method: "DELETE" });
10642
11960
  if (!res.ok) {
@@ -10645,6 +11963,7 @@ function RolesPage() {
10645
11963
  return;
10646
11964
  }
10647
11965
  setSelectedId(null);
11966
+ setDeleteRoleOpen(false);
10648
11967
  await load();
10649
11968
  } catch {
10650
11969
  setError("Delete failed");
@@ -10695,21 +12014,36 @@ function RolesPage() {
10695
12014
  " \u2014 Permissions"
10696
12015
  ] }),
10697
12016
  /* @__PURE__ */ jsxs52(Button, { size: "sm", onClick: saveMatrix, disabled: saving, className: "gap-1", children: [
10698
- /* @__PURE__ */ jsx62(Save6, { className: "h-3.5 w-3.5" }),
12017
+ /* @__PURE__ */ jsx62(Save9, { className: "h-3.5 w-3.5" }),
10699
12018
  saving ? "Saving\u2026" : "Save"
10700
12019
  ] }),
10701
- selected && !isSuperAdminGroupName(selected.name) && /* @__PURE__ */ jsxs52(Button, { size: "sm", variant: "outline", className: "gap-1 text-red-600", onClick: deleteGroup, children: [
12020
+ selected && !isSuperAdminGroupName(selected.name) && /* @__PURE__ */ jsxs52(Button, { size: "sm", variant: "outline", className: "gap-1 text-red-600", onClick: () => setDeleteRoleOpen(true), children: [
10702
12021
  /* @__PURE__ */ jsx62(Trash27, { className: "h-3.5 w-3.5" }),
10703
12022
  "Delete role"
10704
12023
  ] })
10705
12024
  ] }),
10706
12025
  entities.length > 0 && /* @__PURE__ */ jsx62("div", { className: "overflow-x-auto rounded-md border border-gray-200 dark:border-gray-600", children: /* @__PURE__ */ jsxs52("table", { className: "w-full text-sm", children: [
10707
12026
  /* @__PURE__ */ jsx62("thead", { children: /* @__PURE__ */ jsxs52("tr", { className: "border-b bg-gray-50 dark:bg-gray-900/50", children: [
10708
- /* @__PURE__ */ jsx62("th", { className: "p-3 text-left font-medium", children: "Resource" }),
10709
- /* @__PURE__ */ jsx62("th", { className: "p-2", children: "C" }),
10710
- /* @__PURE__ */ jsx62("th", { className: "p-2", children: "R" }),
10711
- /* @__PURE__ */ jsx62("th", { className: "p-2", children: "U" }),
10712
- /* @__PURE__ */ jsx62("th", { className: "p-2", children: "D" })
12027
+ /* @__PURE__ */ jsx62("th", { className: "p-3 text-left font-medium", children: /* @__PURE__ */ jsxs52("div", { className: "flex items-center gap-2", children: [
12028
+ /* @__PURE__ */ jsx62("input", { type: "checkbox", checked: isAllChecked, onChange: toggleAll }),
12029
+ /* @__PURE__ */ jsx62("span", { children: "Resource" })
12030
+ ] }) }),
12031
+ /* @__PURE__ */ jsx62("th", { className: "p-2", children: /* @__PURE__ */ jsxs52("div", { className: "flex items-center justify-center gap-1", children: [
12032
+ /* @__PURE__ */ jsx62("span", { children: "C" }),
12033
+ /* @__PURE__ */ jsx62("input", { type: "checkbox", checked: isColumnAllChecked("canCreate"), onChange: () => toggleColumn("canCreate") })
12034
+ ] }) }),
12035
+ /* @__PURE__ */ jsx62("th", { className: "p-2", children: /* @__PURE__ */ jsxs52("div", { className: "flex items-center justify-center gap-1", children: [
12036
+ /* @__PURE__ */ jsx62("span", { children: "R" }),
12037
+ /* @__PURE__ */ jsx62("input", { type: "checkbox", checked: isColumnAllChecked("canRead"), onChange: () => toggleColumn("canRead") })
12038
+ ] }) }),
12039
+ /* @__PURE__ */ jsx62("th", { className: "p-2", children: /* @__PURE__ */ jsxs52("div", { className: "flex items-center justify-center gap-1", children: [
12040
+ /* @__PURE__ */ jsx62("span", { children: "U" }),
12041
+ /* @__PURE__ */ jsx62("input", { type: "checkbox", checked: isColumnAllChecked("canUpdate"), onChange: () => toggleColumn("canUpdate") })
12042
+ ] }) }),
12043
+ /* @__PURE__ */ jsx62("th", { className: "p-2", children: /* @__PURE__ */ jsxs52("div", { className: "flex items-center justify-center gap-1", children: [
12044
+ /* @__PURE__ */ jsx62("span", { children: "D" }),
12045
+ /* @__PURE__ */ jsx62("input", { type: "checkbox", checked: isColumnAllChecked("canDelete"), onChange: () => toggleColumn("canDelete") })
12046
+ ] }) })
10713
12047
  ] }) }),
10714
12048
  /* @__PURE__ */ jsx62("tbody", { children: entities.map((entity) => {
10715
12049
  const row = matrix[entity];
@@ -10733,7 +12067,15 @@ function RolesPage() {
10733
12067
  /* @__PURE__ */ jsx62(Input, { placeholder: "New role name", value: newName, onChange: (e) => setNewName(e.target.value), onKeyDown: (e) => e.key === "Enter" && createGroup() }),
10734
12068
  /* @__PURE__ */ jsx62(Button, { type: "button", onClick: createGroup, children: "Add role" })
10735
12069
  ] })
10736
- ] })
12070
+ ] }),
12071
+ /* @__PURE__ */ jsx62(Dialog, { open: deleteRoleOpen, onOpenChange: setDeleteRoleOpen, children: /* @__PURE__ */ jsxs52(DialogContent, { children: [
12072
+ /* @__PURE__ */ jsx62(DialogHeader, { children: /* @__PURE__ */ jsx62(DialogTitle, { children: "Delete Role" }) }),
12073
+ /* @__PURE__ */ jsx62("p", { className: "text-sm text-gray-600", children: selected ? `Delete group "${selected.name}"?` : "Delete selected role?" }),
12074
+ /* @__PURE__ */ jsxs52(DialogFooter, { children: [
12075
+ /* @__PURE__ */ jsx62(Button, { variant: "outline", onClick: () => setDeleteRoleOpen(false), children: "Cancel" }),
12076
+ /* @__PURE__ */ jsx62(Button, { variant: "destructive", onClick: deleteGroup, children: "Delete" })
12077
+ ] })
12078
+ ] }) })
10737
12079
  ] });
10738
12080
  }
10739
12081
 
@@ -11011,8 +12353,8 @@ var CRUD_CONFIGS = {
11011
12353
  }
11012
12354
  };
11013
12355
  function BlogEditorWrapper({ blogId }) {
11014
- const [blog, setBlog] = useState35(null);
11015
- const [loading, setLoading] = useState35(!!blogId);
12356
+ const [blog, setBlog] = useState36(null);
12357
+ const [loading, setLoading] = useState36(!!blogId);
11016
12358
  useEffect33(() => {
11017
12359
  if (!blogId) return;
11018
12360
  fetch(`/api/blogs/${blogId}`).then((res) => res.ok ? res.json() : null).then((data) => setBlog(data)).finally(() => setLoading(false));
@@ -11026,8 +12368,8 @@ function BlogEditorWrapper({ blogId }) {
11026
12368
  return /* @__PURE__ */ jsx63(BlogEditor, { existingBlog: blog });
11027
12369
  }
11028
12370
  function AdminPageResolver({ slug }) {
11029
- const router = useRouter13();
11030
- const { customCrudConfigs, storeEnabled } = useContext6(AdminConfigContext);
12371
+ const router = useRouter15();
12372
+ const { customCrudConfigs, storeEnabled } = useContext7(AdminConfigContext);
11031
12373
  const key = slug?.[0] || "dashboard";
11032
12374
  useEffect33(() => {
11033
12375
  if (key === "layout-settings") {
@@ -11089,7 +12431,7 @@ function AdminPageResolver({ slug }) {
11089
12431
  { field: "orderCount", displayName: "Orders" },
11090
12432
  { field: "totalPaid", displayName: "Total paid" }
11091
12433
  ] : crud.columns;
11092
- const extraListParams = useMemo2(
12434
+ const extraListParams = useMemo4(
11093
12435
  () => isContactsWithStore ? { includeSummary: "1" } : void 0,
11094
12436
  [isContactsWithStore]
11095
12437
  );
@@ -11112,21 +12454,21 @@ function AdminPageResolver({ slug }) {
11112
12454
  }
11113
12455
 
11114
12456
  // src/admin/pages/LayoutSettingsPage.tsx
11115
- import { useState as useState36, useEffect as useEffect34, useContext as useContext7 } from "react";
11116
- import { Save as Save7 } from "lucide-react";
12457
+ import { useState as useState37, useEffect as useEffect34, useContext as useContext8 } from "react";
12458
+ import { Save as Save10 } from "lucide-react";
11117
12459
  import { jsx as jsx64, jsxs as jsxs54 } from "react/jsx-runtime";
11118
12460
  function LayoutSettingsPage() {
11119
- const { theme } = useContext7(AdminConfigContext);
11120
- const [activeTab, setActiveTab] = useState36("navbar");
11121
- const [navbarConfig, setNavbarConfig] = useState36({
12461
+ const { theme } = useContext8(AdminConfigContext);
12462
+ const [activeTab, setActiveTab] = useState37("navbar");
12463
+ const [navbarConfig, setNavbarConfig] = useState37({
11122
12464
  logo: "",
11123
12465
  items: [],
11124
12466
  ctaLabel: "",
11125
12467
  ctaUrl: ""
11126
12468
  });
11127
- const [footerValues, setFooterValues] = useState36({});
11128
- const [saving, setSaving] = useState36(false);
11129
- const [loading, setLoading] = useState36(true);
12469
+ const [footerValues, setFooterValues] = useState37({});
12470
+ const [saving, setSaving] = useState37(false);
12471
+ const [loading, setLoading] = useState37(true);
11130
12472
  useEffect34(() => {
11131
12473
  fetch("/api/settings/theme").then((r) => r.ok ? r.json() : null).then((data) => {
11132
12474
  if (!data) return;
@@ -11185,7 +12527,7 @@ function LayoutSettingsPage() {
11185
12527
  disabled: saving,
11186
12528
  className: "bg-white text-gray-800 hover:bg-gray-100 border-0 text-xs",
11187
12529
  children: [
11188
- /* @__PURE__ */ jsx64(Save7, { className: "h-4 w-4 mr-2" }),
12530
+ /* @__PURE__ */ jsx64(Save10, { className: "h-4 w-4 mr-2" }),
11189
12531
  saving ? "Saving..." : "Save"
11190
12532
  ]
11191
12533
  }