gavaengine 2.0.0 → 2.1.0

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.
@@ -2858,17 +2858,138 @@ function ContentList({
2858
2858
  ] });
2859
2859
  }
2860
2860
 
2861
+ // src/components/categories/CategoryManager.tsx
2862
+ import { useState as useState14, useEffect as useEffect7, useCallback as useCallback10 } from "react";
2863
+ import { Fragment as Fragment6, jsx as jsx24, jsxs as jsxs22 } from "react/jsx-runtime";
2864
+ function CategoryManager({
2865
+ getCategories,
2866
+ createCategory,
2867
+ updateCategory,
2868
+ deleteCategory
2869
+ }) {
2870
+ const [categories, setCategories] = useState14([]);
2871
+ const [newName, setNewName] = useState14("");
2872
+ const [editingId, setEditingId] = useState14(null);
2873
+ const [editName, setEditName] = useState14("");
2874
+ const load = useCallback10(async () => {
2875
+ const cats = await getCategories();
2876
+ setCategories(cats);
2877
+ }, [getCategories]);
2878
+ useEffect7(() => {
2879
+ load();
2880
+ }, [load]);
2881
+ const handleCreate = async () => {
2882
+ if (!newName.trim()) return;
2883
+ await createCategory({ name: newName.trim() });
2884
+ setNewName("");
2885
+ load();
2886
+ };
2887
+ const handleUpdate = async (id) => {
2888
+ if (!editName.trim()) return;
2889
+ await updateCategory(id, { name: editName.trim() });
2890
+ setEditingId(null);
2891
+ load();
2892
+ };
2893
+ const handleDelete = async (id, name) => {
2894
+ if (!confirm(`Delete category "${name}"?`)) return;
2895
+ await deleteCategory(id);
2896
+ load();
2897
+ };
2898
+ return /* @__PURE__ */ jsxs22("div", { className: "ge-category-manager", children: [
2899
+ /* @__PURE__ */ jsx24("h2", { children: "Categories" }),
2900
+ /* @__PURE__ */ jsxs22("div", { className: "ge-category-create", style: { display: "flex", gap: "0.5rem", marginBottom: "1rem" }, children: [
2901
+ /* @__PURE__ */ jsx24(
2902
+ "input",
2903
+ {
2904
+ type: "text",
2905
+ value: newName,
2906
+ onChange: (e) => setNewName(e.target.value),
2907
+ placeholder: "New category name",
2908
+ className: "ge-field-input",
2909
+ onKeyDown: (e) => e.key === "Enter" && handleCreate(),
2910
+ style: { flex: 1 }
2911
+ }
2912
+ ),
2913
+ /* @__PURE__ */ jsx24("button", { onClick: handleCreate, className: "ge-btn ge-btn-primary", children: "Add" })
2914
+ ] }),
2915
+ /* @__PURE__ */ jsx24("ul", { className: "ge-category-list", style: { listStyle: "none", padding: 0 }, children: categories.map((cat) => /* @__PURE__ */ jsx24(
2916
+ "li",
2917
+ {
2918
+ style: {
2919
+ display: "flex",
2920
+ alignItems: "center",
2921
+ gap: "0.5rem",
2922
+ padding: "0.5rem 0",
2923
+ borderBottom: "1px solid var(--ge-card-border, #e5e7eb)"
2924
+ },
2925
+ children: editingId === cat.id ? /* @__PURE__ */ jsxs22(Fragment6, { children: [
2926
+ /* @__PURE__ */ jsx24(
2927
+ "input",
2928
+ {
2929
+ type: "text",
2930
+ value: editName,
2931
+ onChange: (e) => setEditName(e.target.value),
2932
+ className: "ge-field-input",
2933
+ style: { flex: 1 },
2934
+ onKeyDown: (e) => e.key === "Enter" && handleUpdate(cat.id),
2935
+ autoFocus: true
2936
+ }
2937
+ ),
2938
+ /* @__PURE__ */ jsx24(
2939
+ "button",
2940
+ {
2941
+ onClick: () => handleUpdate(cat.id),
2942
+ className: "ge-btn ge-btn-small",
2943
+ children: "Save"
2944
+ }
2945
+ ),
2946
+ /* @__PURE__ */ jsx24(
2947
+ "button",
2948
+ {
2949
+ onClick: () => setEditingId(null),
2950
+ className: "ge-btn ge-btn-small",
2951
+ children: "Cancel"
2952
+ }
2953
+ )
2954
+ ] }) : /* @__PURE__ */ jsxs22(Fragment6, { children: [
2955
+ /* @__PURE__ */ jsx24("span", { style: { flex: 1 }, children: cat.name }),
2956
+ /* @__PURE__ */ jsx24(
2957
+ "button",
2958
+ {
2959
+ onClick: () => {
2960
+ setEditingId(cat.id);
2961
+ setEditName(cat.name);
2962
+ },
2963
+ className: "ge-btn ge-btn-small",
2964
+ children: "Edit"
2965
+ }
2966
+ ),
2967
+ /* @__PURE__ */ jsx24(
2968
+ "button",
2969
+ {
2970
+ onClick: () => handleDelete(cat.id, cat.name),
2971
+ className: "ge-btn ge-btn-small ge-btn-danger",
2972
+ children: "Delete"
2973
+ }
2974
+ )
2975
+ ] })
2976
+ },
2977
+ cat.id
2978
+ )) })
2979
+ ] });
2980
+ }
2981
+
2861
2982
  // src/components/dashboard/DashboardNavbar.tsx
2862
2983
  import Link4 from "next/link";
2863
2984
  import { usePathname } from "next/navigation";
2864
2985
  import { useSession, signOut } from "next-auth/react";
2865
2986
  import { FileText as FileText3, Users, LogOut, BarChart3, ImageIcon as ImageIcon3 } from "lucide-react";
2866
- import { useState as useState14 } from "react";
2867
- import { jsx as jsx24, jsxs as jsxs22 } from "react/jsx-runtime";
2987
+ import { useState as useState15 } from "react";
2988
+ import { jsx as jsx25, jsxs as jsxs23 } from "react/jsx-runtime";
2868
2989
  function DashboardNavbar() {
2869
2990
  const pathname = usePathname();
2870
2991
  const { data: session } = useSession();
2871
- const [mobileOpen, setMobileOpen] = useState14(false);
2992
+ const [mobileOpen, setMobileOpen] = useState15(false);
2872
2993
  const { branding, roles, strings, routes } = useGavaConfig();
2873
2994
  const role = session?.user?.role;
2874
2995
  const navigation = [
@@ -2884,10 +3005,10 @@ function DashboardNavbar() {
2884
3005
  ...role === roles.adminRole ? [{ name: strings.users, href: routes.users, icon: Users }] : []
2885
3006
  ];
2886
3007
  const isActive = (href) => pathname.startsWith(href);
2887
- return /* @__PURE__ */ jsx24("header", { className: "sticky top-0 z-50 px-4 pb-4", children: /* @__PURE__ */ jsx24("div", { className: "mx-auto max-w-7xl", children: /* @__PURE__ */ jsxs22("nav", { className: "bg-background/95 backdrop-blur-sm border border-t-transparent border-card-border rounded-b-xl", children: [
2888
- /* @__PURE__ */ jsxs22("div", { className: "flex h-14 items-center justify-between px-6", children: [
2889
- /* @__PURE__ */ jsxs22(Link4, { href: routes.home, className: "flex items-center gap-3", children: [
2890
- branding.logo && /* @__PURE__ */ jsx24("span", { className: "relative z-[9999] -my-[100px] py-[100px] bg-white rounded-b-lg px-1.5 pb-1.5", children: /* @__PURE__ */ jsx24(
3008
+ return /* @__PURE__ */ jsx25("header", { className: "sticky top-0 z-50 px-4 pb-4", children: /* @__PURE__ */ jsx25("div", { className: "mx-auto max-w-7xl", children: /* @__PURE__ */ jsxs23("nav", { className: "bg-background/95 backdrop-blur-sm border border-t-transparent border-card-border rounded-b-xl", children: [
3009
+ /* @__PURE__ */ jsxs23("div", { className: "flex h-14 items-center justify-between px-6", children: [
3010
+ /* @__PURE__ */ jsxs23(Link4, { href: routes.home, className: "flex items-center gap-3", children: [
3011
+ branding.logo && /* @__PURE__ */ jsx25("span", { className: "relative z-[9999] -my-[100px] py-[100px] bg-white rounded-b-lg px-1.5 pb-1.5", children: /* @__PURE__ */ jsx25(
2891
3012
  "img",
2892
3013
  {
2893
3014
  src: branding.logo,
@@ -2896,36 +3017,36 @@ function DashboardNavbar() {
2896
3017
  height: 44
2897
3018
  }
2898
3019
  ) }),
2899
- /* @__PURE__ */ jsx24("span", { className: "font-bold text-lg text-foreground", children: branding.name })
3020
+ /* @__PURE__ */ jsx25("span", { className: "font-bold text-lg text-foreground", children: branding.name })
2900
3021
  ] }),
2901
- /* @__PURE__ */ jsx24("div", { className: "hidden md:flex md:items-center md:gap-6", children: navigation.map((item) => /* @__PURE__ */ jsxs22(
3022
+ /* @__PURE__ */ jsx25("div", { className: "hidden md:flex md:items-center md:gap-6", children: navigation.map((item) => /* @__PURE__ */ jsxs23(
2902
3023
  Link4,
2903
3024
  {
2904
3025
  href: item.href,
2905
3026
  className: `flex items-center gap-2 text-sm font-medium transition-colors ${isActive(item.href) ? "text-accent" : "text-muted hover:text-foreground"}`,
2906
3027
  children: [
2907
- /* @__PURE__ */ jsx24(item.icon, { className: "w-4 h-4" }),
3028
+ /* @__PURE__ */ jsx25(item.icon, { className: "w-4 h-4" }),
2908
3029
  item.name
2909
3030
  ]
2910
3031
  },
2911
3032
  item.name
2912
3033
  )) }),
2913
- /* @__PURE__ */ jsxs22("div", { className: "hidden md:flex md:items-center md:gap-3", children: [
2914
- /* @__PURE__ */ jsxs22("div", { className: "text-right", children: [
2915
- /* @__PURE__ */ jsx24("p", { className: "text-sm font-medium text-foreground leading-tight", children: session?.user?.name }),
2916
- /* @__PURE__ */ jsx24("p", { className: "text-xs text-muted leading-tight", children: roles.labels[role || ""] || role })
3034
+ /* @__PURE__ */ jsxs23("div", { className: "hidden md:flex md:items-center md:gap-3", children: [
3035
+ /* @__PURE__ */ jsxs23("div", { className: "text-right", children: [
3036
+ /* @__PURE__ */ jsx25("p", { className: "text-sm font-medium text-foreground leading-tight", children: session?.user?.name }),
3037
+ /* @__PURE__ */ jsx25("p", { className: "text-xs text-muted leading-tight", children: roles.labels[role || ""] || role })
2917
3038
  ] }),
2918
- /* @__PURE__ */ jsx24(
3039
+ /* @__PURE__ */ jsx25(
2919
3040
  "button",
2920
3041
  {
2921
3042
  onClick: () => signOut({ callbackUrl: routes.login }),
2922
3043
  className: "p-2 rounded-full text-muted hover:text-foreground hover:bg-card transition-colors",
2923
3044
  title: strings.logout,
2924
- children: /* @__PURE__ */ jsx24(LogOut, { className: "w-4 h-4" })
3045
+ children: /* @__PURE__ */ jsx25(LogOut, { className: "w-4 h-4" })
2925
3046
  }
2926
3047
  )
2927
3048
  ] }),
2928
- /* @__PURE__ */ jsxs22(
3049
+ /* @__PURE__ */ jsxs23(
2929
3050
  "button",
2930
3051
  {
2931
3052
  type: "button",
@@ -2933,19 +3054,19 @@ function DashboardNavbar() {
2933
3054
  className: "md:hidden p-2 rounded-full text-foreground flex flex-col justify-center items-center w-10 h-10 gap-1.5",
2934
3055
  "aria-label": "Menu",
2935
3056
  children: [
2936
- /* @__PURE__ */ jsx24(
3057
+ /* @__PURE__ */ jsx25(
2937
3058
  "span",
2938
3059
  {
2939
3060
  className: `block h-0.5 w-5 bg-foreground rounded-full transition-all duration-300 ease-in-out ${mobileOpen ? "rotate-45 translate-y-2" : ""}`
2940
3061
  }
2941
3062
  ),
2942
- /* @__PURE__ */ jsx24(
3063
+ /* @__PURE__ */ jsx25(
2943
3064
  "span",
2944
3065
  {
2945
3066
  className: `block h-0.5 w-5 bg-foreground rounded-full transition-all duration-300 ease-in-out ${mobileOpen ? "opacity-0 scale-0" : ""}`
2946
3067
  }
2947
3068
  ),
2948
- /* @__PURE__ */ jsx24(
3069
+ /* @__PURE__ */ jsx25(
2949
3070
  "span",
2950
3071
  {
2951
3072
  className: `block h-0.5 w-5 bg-foreground rounded-full transition-all duration-300 ease-in-out ${mobileOpen ? "-rotate-45 -translate-y-2" : ""}`
@@ -2955,36 +3076,36 @@ function DashboardNavbar() {
2955
3076
  }
2956
3077
  )
2957
3078
  ] }),
2958
- /* @__PURE__ */ jsx24(
3079
+ /* @__PURE__ */ jsx25(
2959
3080
  "div",
2960
3081
  {
2961
3082
  className: `md:hidden overflow-hidden transition-all duration-300 ease-in-out ${mobileOpen ? "max-h-80 opacity-100" : "max-h-0 opacity-0"}`,
2962
- children: /* @__PURE__ */ jsxs22("div", { className: "py-4 border-t border-card-border mx-6 space-y-1", children: [
2963
- navigation.map((item) => /* @__PURE__ */ jsxs22(
3083
+ children: /* @__PURE__ */ jsxs23("div", { className: "py-4 border-t border-card-border mx-6 space-y-1", children: [
3084
+ navigation.map((item) => /* @__PURE__ */ jsxs23(
2964
3085
  Link4,
2965
3086
  {
2966
3087
  href: item.href,
2967
3088
  onClick: () => setMobileOpen(false),
2968
3089
  className: `flex items-center gap-3 px-3 py-2 rounded-full text-sm font-medium transition-colors ${isActive(item.href) ? "text-accent" : "text-muted hover:text-foreground"}`,
2969
3090
  children: [
2970
- /* @__PURE__ */ jsx24(item.icon, { className: "w-4 h-4" }),
3091
+ /* @__PURE__ */ jsx25(item.icon, { className: "w-4 h-4" }),
2971
3092
  item.name
2972
3093
  ]
2973
3094
  },
2974
3095
  item.name
2975
3096
  )),
2976
- /* @__PURE__ */ jsxs22("div", { className: "pt-3 mt-2 border-t border-card-border", children: [
2977
- /* @__PURE__ */ jsxs22("div", { className: "px-3 mb-2", children: [
2978
- /* @__PURE__ */ jsx24("p", { className: "text-sm font-medium text-foreground", children: session?.user?.name }),
2979
- /* @__PURE__ */ jsx24("p", { className: "text-xs text-muted", children: roles.labels[role || ""] || role })
3097
+ /* @__PURE__ */ jsxs23("div", { className: "pt-3 mt-2 border-t border-card-border", children: [
3098
+ /* @__PURE__ */ jsxs23("div", { className: "px-3 mb-2", children: [
3099
+ /* @__PURE__ */ jsx25("p", { className: "text-sm font-medium text-foreground", children: session?.user?.name }),
3100
+ /* @__PURE__ */ jsx25("p", { className: "text-xs text-muted", children: roles.labels[role || ""] || role })
2980
3101
  ] }),
2981
- /* @__PURE__ */ jsxs22(
3102
+ /* @__PURE__ */ jsxs23(
2982
3103
  "button",
2983
3104
  {
2984
3105
  onClick: () => signOut({ callbackUrl: routes.login }),
2985
3106
  className: "flex items-center gap-3 px-3 py-2 text-sm text-muted hover:text-foreground transition-colors w-full rounded-full hover:bg-card",
2986
3107
  children: [
2987
- /* @__PURE__ */ jsx24(LogOut, { className: "w-4 h-4" }),
3108
+ /* @__PURE__ */ jsx25(LogOut, { className: "w-4 h-4" }),
2988
3109
  strings.logout
2989
3110
  ]
2990
3111
  }
@@ -2997,7 +3118,7 @@ function DashboardNavbar() {
2997
3118
  }
2998
3119
 
2999
3120
  // src/components/dashboard/StatCard.tsx
3000
- import { jsx as jsx25, jsxs as jsxs23 } from "react/jsx-runtime";
3121
+ import { jsx as jsx26, jsxs as jsxs24 } from "react/jsx-runtime";
3001
3122
  var accentStyles = {
3002
3123
  blue: {
3003
3124
  border: "border-l-blue-500",
@@ -3027,23 +3148,23 @@ function StatCard({
3027
3148
  accent = "blue"
3028
3149
  }) {
3029
3150
  const s = accentStyles[accent];
3030
- return /* @__PURE__ */ jsx25(
3151
+ return /* @__PURE__ */ jsx26(
3031
3152
  "div",
3032
3153
  {
3033
3154
  className: `bg-card border border-card-border rounded-xl p-5 border-l-[3px] ${s.border} transition-all duration-200 hover:shadow-sm`,
3034
- children: /* @__PURE__ */ jsxs23("div", { className: "flex items-start justify-between", children: [
3035
- /* @__PURE__ */ jsxs23("div", { children: [
3036
- /* @__PURE__ */ jsx25("p", { className: "text-xs font-medium text-muted uppercase tracking-wide mb-2", children: label }),
3037
- /* @__PURE__ */ jsx25("p", { className: "text-3xl font-bold text-foreground tabular-nums", children: value })
3155
+ children: /* @__PURE__ */ jsxs24("div", { className: "flex items-start justify-between", children: [
3156
+ /* @__PURE__ */ jsxs24("div", { children: [
3157
+ /* @__PURE__ */ jsx26("p", { className: "text-xs font-medium text-muted uppercase tracking-wide mb-2", children: label }),
3158
+ /* @__PURE__ */ jsx26("p", { className: "text-3xl font-bold text-foreground tabular-nums", children: value })
3038
3159
  ] }),
3039
- /* @__PURE__ */ jsx25("div", { className: `p-2 rounded-lg ${s.bg}`, children: /* @__PURE__ */ jsx25(Icon, { className: `w-5 h-5 ${s.text}` }) })
3160
+ /* @__PURE__ */ jsx26("div", { className: `p-2 rounded-lg ${s.bg}`, children: /* @__PURE__ */ jsx26(Icon, { className: `w-5 h-5 ${s.text}` }) })
3040
3161
  ] })
3041
3162
  }
3042
3163
  );
3043
3164
  }
3044
3165
 
3045
3166
  // src/components/splash/SplashScreen.tsx
3046
- import { jsx as jsx26, jsxs as jsxs24 } from "react/jsx-runtime";
3167
+ import { jsx as jsx27, jsxs as jsxs25 } from "react/jsx-runtime";
3047
3168
  var SPLASH_WORDS = ["Powerful", "Flexible", "Modular", "Secure", "Customizable"];
3048
3169
  function pickRandom3() {
3049
3170
  const shuffled = [...SPLASH_WORDS].sort(() => Math.random() - 0.5);
@@ -3055,28 +3176,28 @@ function SplashScreen() {
3055
3176
  if (phase === "idle") return null;
3056
3177
  const topClass = phase === "closing" ? "splash-enter-down" : phase === "opening" ? "splash-exit-up" : "";
3057
3178
  const bottomClass = phase === "closing" ? "splash-enter-up" : phase === "opening" ? "splash-exit-down" : "";
3058
- return /* @__PURE__ */ jsxs24("div", { className: "fixed inset-0 z-[9999] pointer-events-none", children: [
3059
- /* @__PURE__ */ jsx26(
3179
+ return /* @__PURE__ */ jsxs25("div", { className: "fixed inset-0 z-[9999] pointer-events-none", children: [
3180
+ /* @__PURE__ */ jsx27(
3060
3181
  "div",
3061
3182
  {
3062
3183
  className: `splash-half splash-half-top absolute inset-x-0 top-0 h-1/2 bg-background overflow-hidden ${topClass}`,
3063
- children: /* @__PURE__ */ jsx26("div", { className: "absolute inset-0 flex flex-col items-center justify-end pb-2", children: /* @__PURE__ */ jsx26("span", { className: "splash-title", children: "GAVA" }) })
3184
+ children: /* @__PURE__ */ jsx27("div", { className: "absolute inset-0 flex flex-col items-center justify-end pb-2", children: /* @__PURE__ */ jsx27("span", { className: "splash-title", children: "GAVA" }) })
3064
3185
  }
3065
3186
  ),
3066
- /* @__PURE__ */ jsx26(
3187
+ /* @__PURE__ */ jsx27(
3067
3188
  "div",
3068
3189
  {
3069
3190
  className: `splash-half splash-half-bottom absolute inset-x-0 bottom-0 h-1/2 bg-background overflow-hidden ${bottomClass}`,
3070
- children: /* @__PURE__ */ jsxs24("div", { className: "absolute inset-0 flex flex-col items-center justify-start pt-2", children: [
3071
- /* @__PURE__ */ jsx26("span", { className: "splash-title", children: "ENGINE" }),
3072
- /* @__PURE__ */ jsx26("div", { className: "flex items-center gap-3 mt-6", children: words.map((word, i) => /* @__PURE__ */ jsxs24(
3191
+ children: /* @__PURE__ */ jsxs25("div", { className: "absolute inset-0 flex flex-col items-center justify-start pt-2", children: [
3192
+ /* @__PURE__ */ jsx27("span", { className: "splash-title", children: "ENGINE" }),
3193
+ /* @__PURE__ */ jsx27("div", { className: "flex items-center gap-3 mt-6", children: words.map((word, i) => /* @__PURE__ */ jsxs25(
3073
3194
  "span",
3074
3195
  {
3075
3196
  className: "splash-word text-xs sm:text-sm font-medium tracking-widest uppercase",
3076
3197
  style: { animationDelay: `${0.2 + i * 0.1}s` },
3077
3198
  children: [
3078
3199
  word,
3079
- i < 2 && /* @__PURE__ */ jsx26("span", { className: "ml-3 text-muted-foreground", children: "\xB7" })
3200
+ i < 2 && /* @__PURE__ */ jsx27("span", { className: "ml-3 text-muted-foreground", children: "\xB7" })
3080
3201
  ]
3081
3202
  },
3082
3203
  word
@@ -3088,10 +3209,10 @@ function SplashScreen() {
3088
3209
  }
3089
3210
 
3090
3211
  // src/components/splash/DashboardSplashTrigger.tsx
3091
- import { useEffect as useEffect7 } from "react";
3212
+ import { useEffect as useEffect8 } from "react";
3092
3213
  function DashboardSplashTrigger() {
3093
3214
  const { openSplash } = useSplash();
3094
- useEffect7(() => {
3215
+ useEffect8(() => {
3095
3216
  if (typeof window.requestIdleCallback === "function") {
3096
3217
  const id = window.requestIdleCallback(() => openSplash());
3097
3218
  return () => window.cancelIdleCallback(id);
@@ -3131,9 +3252,10 @@ export {
3131
3252
  JsonRenderer,
3132
3253
  ContentEditor,
3133
3254
  ContentList,
3255
+ CategoryManager,
3134
3256
  DashboardNavbar,
3135
3257
  StatCard,
3136
3258
  SplashScreen,
3137
3259
  DashboardSplashTrigger
3138
3260
  };
3139
- //# sourceMappingURL=chunk-YSVQQBBU.js.map
3261
+ //# sourceMappingURL=chunk-5X5LEDAN.js.map