@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.cjs +2067 -740
- package/dist/admin.cjs.map +1 -1
- package/dist/admin.d.cts +4 -0
- package/dist/admin.d.ts +4 -0
- package/dist/admin.js +2019 -677
- package/dist/admin.js.map +1 -1
- package/dist/api.cjs +967 -87
- package/dist/api.cjs.map +1 -1
- package/dist/api.d.cts +1 -1
- package/dist/api.d.ts +1 -1
- package/dist/api.js +962 -84
- package/dist/api.js.map +1 -1
- package/dist/hooks.cjs +159 -0
- package/dist/hooks.cjs.map +1 -1
- package/dist/hooks.d.cts +24 -1
- package/dist/hooks.d.ts +24 -1
- package/dist/hooks.js +165 -0
- package/dist/hooks.js.map +1 -1
- package/dist/{index-CjBf9dAb.d.ts → index-C85X7cc7.d.ts} +16 -2
- package/dist/{index-Be8NLxu-.d.cts → index-h42MoUNq.d.cts} +16 -2
- package/dist/index.cjs +5676 -4456
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +104 -12
- package/dist/index.d.ts +104 -12
- package/dist/index.js +5670 -4467
- package/dist/index.js.map +1 -1
- package/dist/migrations/1775000000000-ProductUomTypeOrderItemSnapshots.ts +29 -0
- package/dist/migrations/1775200000000-MediaDriveFolders.ts +38 -0
- package/package.json +10 -12
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
|
|
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:
|
|
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.
|
|
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] =
|
|
747
|
-
const [moreSheetOpen, setMoreSheetOpen] =
|
|
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] =
|
|
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] =
|
|
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
|
|
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
|
|
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
|
|
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] =
|
|
1097
|
-
const [uploading, setUploading] =
|
|
1098
|
-
const [progress, setProgress] =
|
|
1099
|
-
const [fileUrl, setFileUrl] =
|
|
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
|
|
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] =
|
|
1155
|
-
const [search, setSearch] =
|
|
1156
|
-
const [searchInput, setSearchInput] =
|
|
1157
|
-
const [items, setItems] =
|
|
1158
|
-
const [total, setTotal] =
|
|
1159
|
-
const [page, setPage] =
|
|
1160
|
-
const [loading, setLoading] =
|
|
1161
|
-
const [loadingMore, setLoadingMore] =
|
|
1162
|
-
const [selectedLabel, setSelectedLabel] =
|
|
1163
|
-
const [initialLabelLoaded, setInitialLabelLoaded] =
|
|
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] =
|
|
1338
|
-
const [errors, setErrors] =
|
|
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-
|
|
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,
|
|
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
|
|
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] =
|
|
1712
|
-
const [uniqueColumns, setUniqueColumns] =
|
|
1713
|
-
const [loading, setLoading] =
|
|
1714
|
-
const [importing, setImporting] =
|
|
1715
|
-
const [error, setError] =
|
|
1716
|
-
const [success, setSuccess] =
|
|
1717
|
-
const [parsedData, setParsedData] =
|
|
1718
|
-
const [parseErrors, setParseErrors] =
|
|
1719
|
-
const [upsertKey, setUpsertKey] =
|
|
1720
|
-
const [fileName, setFileName] =
|
|
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
|
|
1989
|
-
const [
|
|
1990
|
-
const [
|
|
1991
|
-
const [
|
|
1992
|
-
const [
|
|
1993
|
-
const [
|
|
1994
|
-
const [
|
|
1995
|
-
const [
|
|
1996
|
-
const [
|
|
1997
|
-
const [
|
|
1998
|
-
const [
|
|
1999
|
-
const [
|
|
2000
|
-
const [
|
|
2001
|
-
const [
|
|
2002
|
-
const [
|
|
2003
|
-
const [
|
|
2004
|
-
const [
|
|
2005
|
-
const [
|
|
2006
|
-
const [
|
|
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
|
-
|
|
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
|
-
|
|
2140
|
+
window.setTimeout(() => {
|
|
2141
|
+
setDeleteDialogOpen(true);
|
|
2142
|
+
}, 0);
|
|
2077
2143
|
};
|
|
2078
2144
|
const handleDelete = async () => {
|
|
2079
|
-
if (!itemToDelete)
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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:
|
|
2293
|
-
onChange: (e) =>
|
|
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(
|
|
2489
|
-
|
|
2490
|
-
|
|
2491
|
-
|
|
2492
|
-
|
|
2493
|
-
|
|
2494
|
-
|
|
2495
|
-
|
|
2496
|
-
|
|
2497
|
-
|
|
2498
|
-
|
|
2499
|
-
|
|
2500
|
-
|
|
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
|
-
|
|
2519
|
-
|
|
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(
|
|
2522
|
-
"
|
|
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
|
-
|
|
2527
|
-
/* @__PURE__ */
|
|
2528
|
-
|
|
2529
|
-
|
|
2530
|
-
|
|
2531
|
-
|
|
2532
|
-
|
|
2533
|
-
|
|
2534
|
-
|
|
2535
|
-
|
|
2536
|
-
|
|
2537
|
-
|
|
2538
|
-
|
|
2539
|
-
|
|
2540
|
-
|
|
2541
|
-
|
|
2542
|
-
|
|
2543
|
-
|
|
2544
|
-
|
|
2545
|
-
"
|
|
2546
|
-
|
|
2547
|
-
|
|
2548
|
-
|
|
2549
|
-
|
|
2550
|
-
|
|
2551
|
-
|
|
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(
|
|
2598
|
-
|
|
2599
|
-
|
|
2600
|
-
|
|
2601
|
-
|
|
2602
|
-
|
|
2603
|
-
|
|
2604
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
|
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] =
|
|
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] =
|
|
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] =
|
|
2960
|
-
const [isLoading, setIsLoading] =
|
|
2961
|
-
const [isSaving, setIsSaving] =
|
|
2962
|
-
const [selectedField, setSelectedField] =
|
|
2963
|
-
const router =
|
|
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__ */
|
|
3129
|
-
|
|
3130
|
-
|
|
3131
|
-
|
|
3132
|
-
|
|
3133
|
-
|
|
3134
|
-
|
|
3135
|
-
|
|
3136
|
-
|
|
3137
|
-
|
|
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
|
-
|
|
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
|
|
3536
|
+
import { useState as useState15, useEffect as useEffect11 } from "react";
|
|
3355
3537
|
|
|
3356
3538
|
// src/components/ui/image-upload.tsx
|
|
3357
|
-
import { useState as
|
|
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] =
|
|
3373
|
-
const [isUploading, setIsUploading] =
|
|
3374
|
-
const [uploadProgress, setUploadProgress] =
|
|
3375
|
-
const [error, setError] =
|
|
3376
|
-
const fileInputRef =
|
|
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
|
|
3740
|
+
import { useRouter as useRouter4 } from "next/navigation";
|
|
3559
3741
|
|
|
3560
3742
|
// src/components/Admin/TagAutocomplete.tsx
|
|
3561
|
-
import { useState as
|
|
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] =
|
|
3571
|
-
const [suggestions, setSuggestions] =
|
|
3572
|
-
const [isLoading, setIsLoading] =
|
|
3573
|
-
const [showSuggestions, setShowSuggestions] =
|
|
3574
|
-
const [isCreating, setIsCreating] =
|
|
3575
|
-
const inputRef =
|
|
3576
|
-
const suggestionsRef =
|
|
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
|
-
|
|
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
|
-
|
|
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 =
|
|
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
|
|
3827
|
-
import { X as X10, Plus as Plus5, Search as Search3, Check as
|
|
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] =
|
|
3836
|
-
const [suggestions, setSuggestions] =
|
|
3837
|
-
const [isLoading, setIsLoading] =
|
|
3838
|
-
const [showSuggestions, setShowSuggestions] =
|
|
3839
|
-
const [isCreating, setIsCreating] =
|
|
3840
|
-
const inputRef =
|
|
3841
|
-
const suggestionsRef =
|
|
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
|
-
|
|
4170
|
+
onMouseDown: (e) => {
|
|
4171
|
+
e.preventDefault();
|
|
4172
|
+
handleSuggestionSelect(category);
|
|
4173
|
+
},
|
|
3983
4174
|
children: [
|
|
3984
4175
|
category.name,
|
|
3985
|
-
selectedCategory === category.name && /* @__PURE__ */ jsx29(
|
|
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
|
-
|
|
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
|
|
4017
|
-
import { X as X11, Search as Search4, Check as
|
|
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] =
|
|
4026
|
-
const [suggestions, setSuggestions] =
|
|
4027
|
-
const [isLoading, setIsLoading] =
|
|
4028
|
-
const [showSuggestions, setShowSuggestions] =
|
|
4029
|
-
const inputRef =
|
|
4030
|
-
const suggestionsRef =
|
|
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
|
-
|
|
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(
|
|
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] =
|
|
4148
|
-
const [slug, setSlug] =
|
|
4149
|
-
const [coverImage, setCoverImage] =
|
|
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] =
|
|
4349
|
+
const [ogImage, setOgImage] = useState15(
|
|
4153
4350
|
existingBlog?.seo?.ogImage || existingBlog?.ogImage || null
|
|
4154
4351
|
);
|
|
4155
|
-
const [metaTitle, setMetaTitle] =
|
|
4156
|
-
const [metaDescription, setMetaDescription] =
|
|
4352
|
+
const [metaTitle, setMetaTitle] = useState15(existingBlog?.seo?.title || "");
|
|
4353
|
+
const [metaDescription, setMetaDescription] = useState15(
|
|
4157
4354
|
existingBlog?.seo?.description || ""
|
|
4158
4355
|
);
|
|
4159
|
-
const [metaKeywords, setMetaKeywords] =
|
|
4356
|
+
const [metaKeywords, setMetaKeywords] = useState15(
|
|
4160
4357
|
existingBlog?.seo?.keywords || ""
|
|
4161
4358
|
);
|
|
4162
|
-
const [published, setPublished] =
|
|
4163
|
-
const [tags, setTags] =
|
|
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] =
|
|
4363
|
+
const [category, setCategory] = useState15(
|
|
4167
4364
|
existingBlog?.category?.name || null
|
|
4168
4365
|
);
|
|
4169
|
-
const [authorId, setAuthorId] =
|
|
4366
|
+
const [authorId, setAuthorId] = useState15(
|
|
4170
4367
|
existingBlog?.authorId || null
|
|
4171
4368
|
);
|
|
4172
|
-
const [content, setContent] =
|
|
4173
|
-
const [createdAt, setCreatedAt] =
|
|
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] =
|
|
4177
|
-
const [isLoading, setIsLoading] =
|
|
4178
|
-
const [isSaving, setIsSaving] =
|
|
4179
|
-
const router =
|
|
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
|
|
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 =
|
|
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
|
|
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] =
|
|
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
|
|
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] =
|
|
4911
|
-
const [pages, setPages] =
|
|
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
|
|
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
|
|
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] =
|
|
5241
|
-
const [password, setPassword] =
|
|
5242
|
-
const [error, setError] =
|
|
5243
|
-
const [loading, setLoading] =
|
|
5244
|
-
const router =
|
|
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
|
|
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] =
|
|
5334
|
-
const [loading, setLoading] =
|
|
5335
|
-
const [message, setMessage] =
|
|
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
|
|
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] =
|
|
5385
|
-
const [loading, setLoading] =
|
|
5386
|
-
const [message, setMessage] =
|
|
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
|
|
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] =
|
|
5687
|
+
const [formData, setFormData] = useState21({
|
|
5463
5688
|
password: "",
|
|
5464
5689
|
confirmPassword: ""
|
|
5465
5690
|
});
|
|
5466
|
-
const [loading, setLoading] =
|
|
5467
|
-
const [message, setMessage] =
|
|
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
|
|
5542
|
-
import {
|
|
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
|
|
5547
|
-
const
|
|
5548
|
-
const [
|
|
5549
|
-
const [
|
|
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(
|
|
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-
|
|
5598
|
-
/* @__PURE__ */ jsxs36("div", { className: "flex items-center
|
|
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: "
|
|
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-
|
|
5603
|
-
/* @__PURE__ */ jsxs36("div", { className: "bg-white rounded border border-gray-200 p-
|
|
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-
|
|
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-
|
|
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-
|
|
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__ */
|
|
5658
|
-
|
|
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(
|
|
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
|
|
5759
|
-
import { useRouter as
|
|
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
|
|
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
|
|
5769
|
-
import { ArrowLeft as ArrowLeft4,
|
|
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 =
|
|
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(
|
|
5806
|
-
/* @__PURE__ */ jsx46(
|
|
5807
|
-
|
|
5808
|
-
|
|
5809
|
-
|
|
5810
|
-
|
|
5811
|
-
|
|
5812
|
-
|
|
5813
|
-
|
|
5814
|
-
|
|
5815
|
-
|
|
5816
|
-
|
|
5817
|
-
|
|
5818
|
-
|
|
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] =
|
|
5841
|
-
const [loading, setLoading] =
|
|
5842
|
-
const [error, setError] =
|
|
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
|
|
6668
|
+
import { useEffect as useEffect21, useState as useState24 } from "react";
|
|
5952
6669
|
import Link10 from "next/link";
|
|
5953
|
-
import { useRouter as
|
|
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
|
|
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 =
|
|
5996
|
-
const [order, setOrder] =
|
|
5997
|
-
const [loading, setLoading] =
|
|
5998
|
-
const [error, setError] =
|
|
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(
|
|
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(
|
|
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(
|
|
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
|
|
7037
|
+
import { useEffect as useEffect22, useState as useState25 } from "react";
|
|
6285
7038
|
import Link11 from "next/link";
|
|
6286
|
-
import { useRouter as
|
|
7039
|
+
import { useRouter as useRouter9 } from "next/navigation";
|
|
6287
7040
|
import { X as X15 } from "lucide-react";
|
|
6288
|
-
import { Fragment as
|
|
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 =
|
|
6298
|
-
const [payment, setPayment] =
|
|
6299
|
-
const [loading, setLoading] =
|
|
6300
|
-
const [error, setError] =
|
|
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(
|
|
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(
|
|
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
|
|
7196
|
+
import { useEffect as useEffect23, useState as useState26 } from "react";
|
|
6444
7197
|
import Link12 from "next/link";
|
|
6445
|
-
import { useRouter as
|
|
7198
|
+
import { useRouter as useRouter10 } from "next/navigation";
|
|
6446
7199
|
import { Plus as Plus7, X as X16 } from "lucide-react";
|
|
6447
|
-
import { Fragment as
|
|
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 =
|
|
6462
|
-
const [contact, setContact] =
|
|
6463
|
-
const [loading, setLoading] =
|
|
6464
|
-
const [error, setError] =
|
|
6465
|
-
const [addAddressOpen, setAddAddressOpen] =
|
|
6466
|
-
const [addAddressSaving, setAddAddressSaving] =
|
|
6467
|
-
const [addAddressForm, setAddAddressForm] =
|
|
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(
|
|
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(
|
|
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(
|
|
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
|
|
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
|
|
7570
|
+
import { toast as toast3 } from "sonner";
|
|
6818
7571
|
import { Save as Save3, RotateCcw } from "lucide-react";
|
|
6819
|
-
import { Fragment as
|
|
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 } =
|
|
6844
|
-
const [tab, setTab] =
|
|
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] =
|
|
6852
|
-
const [loading, setLoading] =
|
|
6853
|
-
const [saving, setSaving] =
|
|
6854
|
-
const [activeThemeId, setActiveThemeId] =
|
|
6855
|
-
const [navbarConfig, setNavbarConfig] =
|
|
6856
|
-
const [themeSettingsLoading, setThemeSettingsLoading] =
|
|
6857
|
-
const [storeEnabled, setStoreEnabled] =
|
|
6858
|
-
const [storeSettingsLoading, setStoreSettingsLoading] =
|
|
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
|
-
|
|
7657
|
+
toast3.success("Settings saved");
|
|
6905
7658
|
} catch {
|
|
6906
|
-
|
|
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
|
-
|
|
7673
|
+
toast3.success("Theme updated");
|
|
6921
7674
|
window.location.reload();
|
|
6922
7675
|
} catch {
|
|
6923
|
-
|
|
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
|
-
|
|
7689
|
+
toast3.success("Navbar saved");
|
|
6937
7690
|
} catch {
|
|
6938
|
-
|
|
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
|
-
|
|
7704
|
+
toast3.success("Store settings saved");
|
|
6952
7705
|
window.location.reload();
|
|
6953
7706
|
} catch {
|
|
6954
|
-
|
|
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(
|
|
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(
|
|
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
|
|
7071
|
-
|
|
7072
|
-
|
|
7073
|
-
import {
|
|
7074
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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] =
|
|
7113
|
-
const [loading, setLoading] =
|
|
7114
|
-
const [page, setPage] =
|
|
7115
|
-
const [totalPages, setTotalPages] =
|
|
7116
|
-
const [search, setSearch] =
|
|
7117
|
-
const [searchInput, setSearchInput] =
|
|
7118
|
-
const [typeFilter, setTypeFilter] =
|
|
7119
|
-
const [
|
|
7120
|
-
const [
|
|
7121
|
-
const [
|
|
7122
|
-
const [
|
|
7123
|
-
const
|
|
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
|
|
7130
|
-
sortOrder
|
|
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
|
-
|
|
7992
|
+
toast4.success("File uploaded");
|
|
7177
7993
|
load();
|
|
7178
7994
|
} catch (err) {
|
|
7179
|
-
|
|
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
|
|
7186
|
-
|
|
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(
|
|
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
|
-
|
|
8047
|
+
toast4.success("Deleted");
|
|
8048
|
+
setDeleteTarget(null);
|
|
7191
8049
|
load();
|
|
7192
8050
|
} catch {
|
|
7193
|
-
|
|
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(
|
|
8066
|
+
body: JSON.stringify(body)
|
|
7203
8067
|
});
|
|
7204
8068
|
if (!res.ok) throw new Error("Update failed");
|
|
7205
|
-
|
|
8069
|
+
toast4.success("Updated");
|
|
7206
8070
|
setEditModal(null);
|
|
7207
8071
|
load();
|
|
7208
8072
|
} catch {
|
|
7209
|
-
|
|
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
|
-
|
|
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
|
|
7223
|
-
const
|
|
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: "
|
|
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
|
|
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: "
|
|
7284
|
-
|
|
7285
|
-
|
|
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(
|
|
7291
|
-
|
|
7292
|
-
|
|
7293
|
-
|
|
7294
|
-
|
|
7295
|
-
|
|
7296
|
-
|
|
7297
|
-
|
|
7298
|
-
|
|
7299
|
-
|
|
7300
|
-
|
|
7301
|
-
|
|
7302
|
-
|
|
7303
|
-
|
|
7304
|
-
|
|
7305
|
-
|
|
7306
|
-
|
|
7307
|
-
|
|
7308
|
-
|
|
7309
|
-
|
|
7310
|
-
|
|
7311
|
-
|
|
7312
|
-
|
|
7313
|
-
|
|
7314
|
-
|
|
7315
|
-
|
|
7316
|
-
|
|
7317
|
-
|
|
7318
|
-
|
|
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
|
-
|
|
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__ */
|
|
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
|
|
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
|
|
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
|
|
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 =
|
|
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] =
|
|
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] =
|
|
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] =
|
|
7823
|
-
const [propertiesOpen, setPropertiesOpen] =
|
|
7824
|
-
const [layoutOpen, setLayoutOpen] =
|
|
7825
|
-
const [layersOpen, setLayersOpen] =
|
|
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(
|
|
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] =
|
|
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 } =
|
|
7966
|
-
const router =
|
|
7967
|
-
const [title, setTitle] =
|
|
7968
|
-
const [slug, setSlug] =
|
|
7969
|
-
const [published, setPublished] =
|
|
7970
|
-
const [initialContent, setInitialContent] =
|
|
7971
|
-
const [loading, setLoading] =
|
|
7972
|
-
const [rightTab, setRightTab] =
|
|
7973
|
-
const [seoTitle, setSeoTitle] =
|
|
7974
|
-
const [seoDescription, setSeoDescription] =
|
|
7975
|
-
const [seoKeywords, setSeoKeywords] =
|
|
7976
|
-
const [seoOgTitle, setSeoOgTitle] =
|
|
7977
|
-
const [seoOgDescription, setSeoOgDescription] =
|
|
7978
|
-
const [seoOgImage, setSeoOgImage] =
|
|
7979
|
-
const [pageSeoId, setPageSeoId] =
|
|
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: "
|
|
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
|
|
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
|
|
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(
|
|
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
|
|
8176
|
-
import { Fragment as
|
|
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] =
|
|
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] =
|
|
8318
|
-
const [botName, setBotName] =
|
|
8319
|
-
const [icon, setIcon] =
|
|
8320
|
-
const [iconImageUrl, setIconImageUrl] =
|
|
8321
|
-
const [iconBackgroundColor, setIconBackgroundColor] =
|
|
8322
|
-
const [headerColor, setHeaderColor] =
|
|
8323
|
-
const [salesTeamEmails, setSalesTeamEmails] =
|
|
8324
|
-
const [fulfilmentTeamEmails, setFulfilmentTeamEmails] =
|
|
8325
|
-
const [crmEmails, setCrmEmails] =
|
|
8326
|
-
const [logoUrl, setLogoUrl] =
|
|
8327
|
-
const [companyName, setCompanyName] =
|
|
8328
|
-
const [supportEmail, setSupportEmail] =
|
|
8329
|
-
const [supportPhone, setSupportPhone] =
|
|
8330
|
-
const [followUsTitle, setFollowUsTitle] =
|
|
8331
|
-
const [socialLinkRows, setSocialLinkRows] =
|
|
8332
|
-
const [footerDisclaimer, setFooterDisclaimer] =
|
|
8333
|
-
const [chatMode, setChatMode] =
|
|
8334
|
-
const [whatsappPhone, setWhatsappPhone] =
|
|
8335
|
-
const [externalChatSnippet, setExternalChatSnippet] =
|
|
8336
|
-
const [erpPipelineName, setErpPipelineName] =
|
|
8337
|
-
const [erpPipelineStageName, setErpPipelineStageName] =
|
|
8338
|
-
const [erpFormsCatalog, setErpFormsCatalog] =
|
|
8339
|
-
const [erpOpportunityFormIds, setErpOpportunityFormIds] =
|
|
8340
|
-
const [erpOpportunityIdsKeyPresent, setErpOpportunityIdsKeyPresent] =
|
|
8341
|
-
const [smsProviderChoice, setSmsProviderChoice] =
|
|
8342
|
-
const [msg91ApiMode, setMsg91ApiMode] =
|
|
8343
|
-
const [smsTplItems, setSmsTplItems] =
|
|
8344
|
-
const [loading, setLoading] =
|
|
8345
|
-
const [saving, setSaving] =
|
|
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
|
-
|
|
9567
|
+
toast5.success("Settings saved");
|
|
8488
9568
|
onSaved?.();
|
|
8489
9569
|
} catch {
|
|
8490
|
-
|
|
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(
|
|
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 = [] } =
|
|
9107
|
-
const [selectedName, setSelectedName] =
|
|
9108
|
-
const [enabledMap, setEnabledMap] =
|
|
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(
|
|
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
|
|
9171
|
-
import { useRouter as
|
|
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
|
|
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 =
|
|
10346
|
+
const router = useRouter12();
|
|
9267
10347
|
const create = isCreate(brandId);
|
|
9268
|
-
const [loading, setLoading] =
|
|
9269
|
-
const [saving, setSaving] =
|
|
9270
|
-
const [errors, setErrors] =
|
|
9271
|
-
const [name, setName] =
|
|
9272
|
-
const [slug, setSlug] =
|
|
9273
|
-
const [description, setDescription] =
|
|
9274
|
-
const [logo, setLogo] =
|
|
9275
|
-
const [active, setActive] =
|
|
9276
|
-
const [sortOrder, setSortOrder] =
|
|
9277
|
-
const [seoId, setSeoId] =
|
|
9278
|
-
const [seo, setSeo] =
|
|
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(
|
|
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(
|
|
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
|
|
9469
|
-
import { useRouter as
|
|
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
|
|
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] =
|
|
9485
|
-
const [open, setOpen] =
|
|
9486
|
-
const [list, setList] =
|
|
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
|
-
|
|
9489
|
-
|
|
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: () =>
|
|
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
|
|
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 =
|
|
10728
|
+
const router = useRouter13();
|
|
9642
10729
|
const create = isCreate2(productId);
|
|
9643
|
-
const [loading, setLoading] =
|
|
9644
|
-
const [saving, setSaving] =
|
|
9645
|
-
const [errors, setErrors] =
|
|
9646
|
-
const [collections, setCollections] =
|
|
9647
|
-
const [brands, setBrands] =
|
|
9648
|
-
const [categories, setCategories] =
|
|
9649
|
-
const [name, setName] =
|
|
9650
|
-
const [productSlug, setProductSlug] =
|
|
9651
|
-
const [sku, setSku] =
|
|
9652
|
-
const [hsn, setHsn] =
|
|
9653
|
-
const [
|
|
9654
|
-
const [
|
|
9655
|
-
const [
|
|
9656
|
-
const [
|
|
9657
|
-
const [
|
|
9658
|
-
const [
|
|
9659
|
-
const [
|
|
9660
|
-
const [
|
|
9661
|
-
const [
|
|
9662
|
-
const [
|
|
9663
|
-
const [
|
|
9664
|
-
const [
|
|
9665
|
-
const [
|
|
9666
|
-
const [
|
|
9667
|
-
const [
|
|
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(
|
|
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
|
|
10137
|
-
import { useRouter as
|
|
10138
|
-
import { AlertCircle as AlertCircle6, Plus as Plus10, Trash2 as Trash26, ChevronDown as ChevronDown6, ChevronUp as ChevronUp2 } from "lucide-react";
|
|
10139
|
-
import { Fragment as
|
|
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 =
|
|
11426
|
+
const router = useRouter14();
|
|
10148
11427
|
const create = isCreate3(collectionId);
|
|
10149
|
-
const [loading, setLoading] =
|
|
10150
|
-
const [saving, setSaving] =
|
|
10151
|
-
const [errors, setErrors] =
|
|
10152
|
-
const [categories, setCategories] =
|
|
10153
|
-
const [brands, setBrands] =
|
|
10154
|
-
const [name, setName] =
|
|
10155
|
-
const [slug, setSlug] =
|
|
10156
|
-
const [hsn, setHsn] =
|
|
10157
|
-
const [categoryId, setCategoryId] =
|
|
10158
|
-
const [brandId, setBrandId] =
|
|
10159
|
-
const [description, setDescription] =
|
|
10160
|
-
const [image, setImage] =
|
|
10161
|
-
const [active, setActive] =
|
|
10162
|
-
const [sortOrder, setSortOrder] =
|
|
10163
|
-
const [advancedOpen, setAdvancedOpen] =
|
|
10164
|
-
const [heroSlides, setHeroSlides] =
|
|
10165
|
-
const [variants, setVariants] =
|
|
10166
|
-
const [experienceDescription, setExperienceDescription] =
|
|
10167
|
-
const [brochureUrl, setBrochureUrl] =
|
|
10168
|
-
const [seoId, setSeoId] =
|
|
10169
|
-
const [seo, setSeo] =
|
|
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(
|
|
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(
|
|
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
|
|
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
|
|
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] =
|
|
10530
|
-
const [groups, setGroups] =
|
|
10531
|
-
const [selectedId, setSelectedId] =
|
|
10532
|
-
const [matrix, setMatrix] =
|
|
10533
|
-
const [loading, setLoading] =
|
|
10534
|
-
const [saving, setSaving] =
|
|
10535
|
-
const [newName, setNewName] =
|
|
10536
|
-
const [
|
|
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(
|
|
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:
|
|
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: "
|
|
10709
|
-
|
|
10710
|
-
|
|
10711
|
-
|
|
10712
|
-
/* @__PURE__ */ jsx62("th", { className: "p-2", children: "
|
|
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] =
|
|
11015
|
-
const [loading, setLoading] =
|
|
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 =
|
|
11030
|
-
const { customCrudConfigs, storeEnabled } =
|
|
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 =
|
|
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
|
|
11116
|
-
import { Save as
|
|
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 } =
|
|
11120
|
-
const [activeTab, setActiveTab] =
|
|
11121
|
-
const [navbarConfig, setNavbarConfig] =
|
|
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] =
|
|
11128
|
-
const [saving, setSaving] =
|
|
11129
|
-
const [loading, setLoading] =
|
|
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(
|
|
12530
|
+
/* @__PURE__ */ jsx64(Save10, { className: "h-4 w-4 mr-2" }),
|
|
11189
12531
|
saving ? "Saving..." : "Save"
|
|
11190
12532
|
]
|
|
11191
12533
|
}
|