@carlonicora/nextjs-jsonapi 1.39.2 → 1.40.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.
Files changed (84) hide show
  1. package/dist/{BlockNoteEditor-WQXQPLMX.js → BlockNoteEditor-4G3L3LSF.js} +14 -14
  2. package/dist/{BlockNoteEditor-WQXQPLMX.js.map → BlockNoteEditor-4G3L3LSF.js.map} +1 -1
  3. package/dist/{BlockNoteEditor-CITC7I2Z.mjs → BlockNoteEditor-EKY4AHVK.mjs} +4 -4
  4. package/dist/billing/index.js +346 -346
  5. package/dist/billing/index.mjs +3 -3
  6. package/dist/{chunk-LDH2FGJY.mjs → chunk-BAOP6PTD.mjs} +689 -34
  7. package/dist/chunk-BAOP6PTD.mjs.map +1 -0
  8. package/dist/{chunk-2RBYXY6T.js → chunk-GKY5DAIH.js} +1228 -573
  9. package/dist/chunk-GKY5DAIH.js.map +1 -0
  10. package/dist/{chunk-TQ5GRRTM.mjs → chunk-GVN7XC3U.mjs} +278 -2
  11. package/dist/chunk-GVN7XC3U.mjs.map +1 -0
  12. package/dist/{chunk-XLMJPA4N.mjs → chunk-RRIYLEY6.mjs} +22 -2
  13. package/dist/chunk-RRIYLEY6.mjs.map +1 -0
  14. package/dist/{chunk-2PHWAL6Q.js → chunk-T5YYOT4Z.js} +22 -2
  15. package/dist/chunk-T5YYOT4Z.js.map +1 -0
  16. package/dist/{chunk-3EZX4G2E.js → chunk-ZNGEVB5M.js} +279 -3
  17. package/dist/chunk-ZNGEVB5M.js.map +1 -0
  18. package/dist/client/index.js +4 -4
  19. package/dist/client/index.mjs +3 -3
  20. package/dist/components/index.d.mts +28 -4
  21. package/dist/components/index.d.ts +28 -4
  22. package/dist/components/index.js +16 -4
  23. package/dist/components/index.js.map +1 -1
  24. package/dist/components/index.mjs +15 -3
  25. package/dist/contexts/index.js +4 -4
  26. package/dist/contexts/index.mjs +3 -3
  27. package/dist/core/index.d.mts +127 -3
  28. package/dist/core/index.d.ts +127 -3
  29. package/dist/core/index.js +12 -2
  30. package/dist/core/index.js.map +1 -1
  31. package/dist/core/index.mjs +11 -1
  32. package/dist/index.d.mts +5 -2
  33. package/dist/index.d.ts +5 -2
  34. package/dist/index.js +17 -3
  35. package/dist/index.js.map +1 -1
  36. package/dist/index.mjs +16 -2
  37. package/dist/{s3.service-hnTPVTm2.d.mts → s3.service-BoOF5-ln.d.mts} +1 -0
  38. package/dist/{s3.service-DXkDoMf1.d.ts → s3.service-Mxo-7wQ6.d.ts} +1 -0
  39. package/dist/server/index.d.mts +1 -1
  40. package/dist/server/index.d.ts +1 -1
  41. package/dist/server/index.js +3 -3
  42. package/dist/server/index.mjs +1 -1
  43. package/dist/waitlist.config-kPfjImle.d.mts +26 -0
  44. package/dist/waitlist.config-kPfjImle.d.ts +26 -0
  45. package/package.json +1 -1
  46. package/src/components/forms/FormCheckbox.tsx +1 -1
  47. package/src/components/forms/FormSelect.tsx +1 -1
  48. package/src/components/index.ts +1 -0
  49. package/src/core/index.ts +3 -0
  50. package/src/core/registry/ModuleRegistry.ts +3 -0
  51. package/src/features/auth/components/forms/Register.tsx +180 -1
  52. package/src/features/auth/data/auth.interface.ts +1 -0
  53. package/src/features/auth/data/auth.ts +1 -0
  54. package/src/features/index.ts +1 -0
  55. package/src/features/waitlist/components/forms/WaitlistForm.tsx +186 -0
  56. package/src/features/waitlist/components/forms/WaitlistQuestionnaireRenderer.tsx +110 -0
  57. package/src/features/waitlist/components/forms/index.ts +2 -0
  58. package/src/features/waitlist/components/index.ts +3 -0
  59. package/src/features/waitlist/components/lists/WaitlistList.tsx +145 -0
  60. package/src/features/waitlist/components/lists/index.ts +1 -0
  61. package/src/features/waitlist/components/sections/WaitlistConfirmation.tsx +68 -0
  62. package/src/features/waitlist/components/sections/WaitlistHeroSection.tsx +49 -0
  63. package/src/features/waitlist/components/sections/WaitlistSuccessState.tsx +19 -0
  64. package/src/features/waitlist/components/sections/index.ts +3 -0
  65. package/src/features/waitlist/config/waitlist.config.ts +35 -0
  66. package/src/features/waitlist/data/Waitlist.ts +104 -0
  67. package/src/features/waitlist/data/WaitlistInterface.ts +32 -0
  68. package/src/features/waitlist/data/WaitlistService.ts +153 -0
  69. package/src/features/waitlist/data/index.ts +5 -0
  70. package/src/features/waitlist/data/waitlist-stats.interface.ts +9 -0
  71. package/src/features/waitlist/data/waitlist-stats.ts +47 -0
  72. package/src/features/waitlist/hooks/useWaitlistTableStructure.tsx +121 -0
  73. package/src/features/waitlist/index.ts +28 -0
  74. package/src/features/waitlist/waitlist-stats.module.ts +8 -0
  75. package/src/features/waitlist/waitlist.module.ts +9 -0
  76. package/src/index.ts +9 -0
  77. package/src/login/config.ts +9 -0
  78. package/dist/chunk-2PHWAL6Q.js.map +0 -1
  79. package/dist/chunk-2RBYXY6T.js.map +0 -1
  80. package/dist/chunk-3EZX4G2E.js.map +0 -1
  81. package/dist/chunk-LDH2FGJY.mjs.map +0 -1
  82. package/dist/chunk-TQ5GRRTM.mjs.map +0 -1
  83. package/dist/chunk-XLMJPA4N.mjs.map +0 -1
  84. /package/dist/{BlockNoteEditor-CITC7I2Z.mjs.map → BlockNoteEditor-EKY4AHVK.mjs.map} +0 -0
@@ -2,8 +2,10 @@ import {
2
2
  getApiUrl,
3
3
  getAppUrl,
4
4
  getI18nLink,
5
+ getRegistrationMode,
5
6
  getRoleId,
6
7
  getTrackablePages,
8
+ getWaitlistConfig,
7
9
  isDiscordAuthEnabled,
8
10
  isGoogleAuthEnabled,
9
11
  isInternalAuthEnabled,
@@ -13,7 +15,7 @@ import {
13
15
  useI18nLocale,
14
16
  useI18nRouter,
15
17
  useI18nTranslations
16
- } from "./chunk-XLMJPA4N.mjs";
18
+ } from "./chunk-RRIYLEY6.mjs";
17
19
  import {
18
20
  AVAILABLE_OAUTH_SCOPES,
19
21
  AuthService,
@@ -31,6 +33,7 @@ import {
31
33
  RoleService,
32
34
  S3Service,
33
35
  UserService,
36
+ WaitlistService,
34
37
  checkPermissions,
35
38
  cn,
36
39
  getIconByModule,
@@ -41,7 +44,7 @@ import {
41
44
  showToast,
42
45
  useComposedRefs,
43
46
  useIsMobile
44
- } from "./chunk-TQ5GRRTM.mjs";
47
+ } from "./chunk-GVN7XC3U.mjs";
45
48
  import {
46
49
  JsonApiContext
47
50
  } from "./chunk-VOXD3ZLY.mjs";
@@ -7447,7 +7450,7 @@ function FormCheckbox({ form, id, name, labelBefore, description, isRequired })
7447
7450
  return /* @__PURE__ */ jsx64("div", { className: "flex w-full flex-col", children: /* @__PURE__ */ jsx64(FormFieldWrapper, { form, name: id, orientation: "horizontal", children: (field) => /* @__PURE__ */ jsxs34("div", { className: "flex gap-x-4", children: [
7448
7451
  labelBefore && label(),
7449
7452
  labelBefore && isRequired && /* @__PURE__ */ jsx64("span", { className: "text-destructive ml-2 font-semibold", children: "*" }),
7450
- /* @__PURE__ */ jsx64(Checkbox, { id, defaultChecked: field.value, onCheckedChange: field.onChange }),
7453
+ /* @__PURE__ */ jsx64(Checkbox, { id, checked: field.value ?? false, onCheckedChange: field.onChange }),
7451
7454
  !labelBefore && label(),
7452
7455
  !labelBefore && isRequired && /* @__PURE__ */ jsx64("span", { className: "text-destructive ml-2 font-semibold", children: "*" })
7453
7456
  ] }) }) });
@@ -8126,7 +8129,7 @@ function FormSelect({
8126
8129
  disabled,
8127
8130
  "data-testid": testId,
8128
8131
  children: [
8129
- /* @__PURE__ */ jsx71(SelectTrigger, { className: "w-full", children: /* @__PURE__ */ jsx71(SelectValue, {}) }),
8132
+ /* @__PURE__ */ jsx71(SelectTrigger, { className: "w-full", children: /* @__PURE__ */ jsx71(SelectValue, { children: values.find((v) => v.id === field.value)?.text }) }),
8130
8133
  /* @__PURE__ */ jsx71(SelectContent, { children: values.map((type) => /* @__PURE__ */ jsx71(SelectItem, { value: type.id, children: type.text }, type.id)) })
8131
8134
  ]
8132
8135
  }
@@ -10844,7 +10847,7 @@ __name(AllowedUsersDetails, "AllowedUsersDetails");
10844
10847
  import dynamic from "next/dynamic";
10845
10848
  import React15 from "react";
10846
10849
  import { jsx as jsx125 } from "react/jsx-runtime";
10847
- var BlockNoteEditor = dynamic(() => import("./BlockNoteEditor-CITC7I2Z.mjs"), {
10850
+ var BlockNoteEditor = dynamic(() => import("./BlockNoteEditor-EKY4AHVK.mjs"), {
10848
10851
  ssr: false
10849
10852
  });
10850
10853
  var BlockNoteEditorContainer = React15.memo(/* @__PURE__ */ __name(function EditorContainer(props) {
@@ -12148,9 +12151,11 @@ import { createContext as createContext16, useContext as useContext17, useMemo a
12148
12151
 
12149
12152
  // src/features/auth/components/forms/Register.tsx
12150
12153
  import { zodResolver as zodResolver4 } from "@hookform/resolvers/zod";
12154
+ import { Loader2 as Loader23 } from "lucide-react";
12151
12155
  import { useTranslations as useTranslations48 } from "next-intl";
12152
12156
  import Image7 from "next/image";
12153
- import { useState as useState46 } from "react";
12157
+ import { useSearchParams } from "next/navigation";
12158
+ import { useEffect as useEffect40, useState as useState46 } from "react";
12154
12159
  import { useForm as useForm4 } from "react-hook-form";
12155
12160
  import { v4 as v44 } from "uuid";
12156
12161
  import { z as z4 } from "zod";
@@ -12193,7 +12198,15 @@ import { Fragment as Fragment20, jsx as jsx140, jsxs as jsxs81 } from "react/jsx
12193
12198
  function Register() {
12194
12199
  const t = useTranslations48();
12195
12200
  const { setComponentType } = useAuthContext();
12201
+ const searchParams = useSearchParams();
12202
+ const inviteCode = searchParams.get("invite");
12203
+ const registrationMode = getRegistrationMode();
12196
12204
  const [showConfirmation, setShowConfirmation] = useState46(false);
12205
+ const [inviteValidated, setInviteValidated] = useState46(false);
12206
+ const [inviteError, setInviteError] = useState46("");
12207
+ const [isValidatingInvite, setIsValidatingInvite] = useState46(
12208
+ registrationMode === "waitlist" && !!inviteCode
12209
+ );
12197
12210
  const formSchema = z4.object({
12198
12211
  company: z4.string().min(1, {
12199
12212
  message: t(`common.errors.missing_company_name`)
@@ -12223,6 +12236,37 @@ function Register() {
12223
12236
  marketingConsent: false
12224
12237
  }
12225
12238
  });
12239
+ useEffect40(() => {
12240
+ async function validateInvite() {
12241
+ console.log("[Register] validateInvite called. registrationMode:", registrationMode, "inviteCode:", inviteCode);
12242
+ if (registrationMode !== "waitlist" || !inviteCode) {
12243
+ console.log("[Register] Skipping validation - not in waitlist mode or no invite code");
12244
+ return;
12245
+ }
12246
+ setIsValidatingInvite(true);
12247
+ try {
12248
+ console.log("[Register] Calling WaitlistService.validateInvite...");
12249
+ const result = await WaitlistService.validateInvite(inviteCode);
12250
+ console.log("[Register] Validation result:", JSON.stringify(result));
12251
+ if (result && result.valid) {
12252
+ console.log("[Register] Invite valid! Email:", result.email);
12253
+ setInviteValidated(true);
12254
+ form.setValue("email", result.email);
12255
+ } else {
12256
+ const errorMsg = result ? t("waitlist.invite.error_expired") : t("waitlist.invite.error_invalid");
12257
+ console.log("[Register] Invite invalid. result:", result, "errorMsg:", errorMsg);
12258
+ setInviteError(errorMsg);
12259
+ }
12260
+ } catch (error) {
12261
+ console.error("[Register] Validation exception:", error);
12262
+ setInviteError(t("waitlist.invite.error_validation_failed"));
12263
+ } finally {
12264
+ setIsValidatingInvite(false);
12265
+ }
12266
+ }
12267
+ __name(validateInvite, "validateInvite");
12268
+ validateInvite();
12269
+ }, [registrationMode, inviteCode, form, t]);
12226
12270
  const onSubmit = /* @__PURE__ */ __name(async (values) => {
12227
12271
  try {
12228
12272
  const payload = {
@@ -12233,7 +12277,8 @@ function Register() {
12233
12277
  password: values.password,
12234
12278
  termsAcceptedAt: (/* @__PURE__ */ new Date()).toISOString(),
12235
12279
  marketingConsent: values.marketingConsent ?? false,
12236
- marketingConsentAt: values.marketingConsent ? (/* @__PURE__ */ new Date()).toISOString() : null
12280
+ marketingConsentAt: values.marketingConsent ? (/* @__PURE__ */ new Date()).toISOString() : null,
12281
+ inviteCode: inviteCode ?? void 0
12237
12282
  };
12238
12283
  await AuthService.register(payload);
12239
12284
  setShowConfirmation(true);
@@ -12241,6 +12286,45 @@ function Register() {
12241
12286
  errorToast({ error: e });
12242
12287
  }
12243
12288
  }, "onSubmit");
12289
+ if (registrationMode === "waitlist" && inviteCode && isValidatingInvite) {
12290
+ return /* @__PURE__ */ jsxs81(Fragment20, { children: [
12291
+ /* @__PURE__ */ jsx140(CardHeader, { children: /* @__PURE__ */ jsxs81(CardTitle, { className: "text-primary flex flex-col items-center pb-10 text-4xl", children: [
12292
+ /* @__PURE__ */ jsx140(Image7, { src: "/logo.webp", alt: "Logo", width: 100, height: 100, priority: true }),
12293
+ t("waitlist.invite.validating_title")
12294
+ ] }) }),
12295
+ /* @__PURE__ */ jsxs81(CardContent, { className: "flex flex-col items-center justify-center space-y-4 py-8", children: [
12296
+ /* @__PURE__ */ jsx140(Loader23, { className: "h-8 w-8 animate-spin text-primary" }),
12297
+ /* @__PURE__ */ jsx140("p", { className: "text-muted-foreground", children: t("waitlist.invite.validating_description") })
12298
+ ] })
12299
+ ] });
12300
+ }
12301
+ if (registrationMode === "waitlist" && inviteCode && inviteError) {
12302
+ return /* @__PURE__ */ jsxs81(Fragment20, { children: [
12303
+ /* @__PURE__ */ jsx140(CardHeader, { children: /* @__PURE__ */ jsxs81(CardTitle, { className: "text-primary flex flex-col items-center pb-10 text-4xl", children: [
12304
+ /* @__PURE__ */ jsx140(Image7, { src: "/logo.webp", alt: "Logo", width: 100, height: 100, priority: true }),
12305
+ t("waitlist.invite.invalid_title")
12306
+ ] }) }),
12307
+ /* @__PURE__ */ jsxs81(CardContent, { className: "text-center", children: [
12308
+ /* @__PURE__ */ jsx140("p", { className: "text-destructive mb-4", children: inviteError }),
12309
+ /* @__PURE__ */ jsx140("p", { className: "mb-4", children: t("waitlist.invite.join_prompt") }),
12310
+ /* @__PURE__ */ jsx140(Link, { href: "/waitlist", className: "text-primary underline", children: t("waitlist.invite.join_link") })
12311
+ ] })
12312
+ ] });
12313
+ }
12314
+ if (registrationMode === "waitlist" && !inviteCode) {
12315
+ return /* @__PURE__ */ jsxs81(Fragment20, { children: [
12316
+ /* @__PURE__ */ jsx140(CardHeader, { children: /* @__PURE__ */ jsxs81(CardTitle, { className: "text-primary flex flex-col items-center pb-10 text-4xl", children: [
12317
+ /* @__PURE__ */ jsx140(Image7, { src: "/logo.webp", alt: "Logo", width: 100, height: 100, priority: true }),
12318
+ t("waitlist.invite.registration_title")
12319
+ ] }) }),
12320
+ /* @__PURE__ */ jsxs81(CardContent, { className: "text-center", children: [
12321
+ /* @__PURE__ */ jsx140("p", { className: "mb-4", children: t("waitlist.invite.registration_description") }),
12322
+ /* @__PURE__ */ jsx140("p", { className: "mb-4", children: t("waitlist.invite.registration_hint") }),
12323
+ /* @__PURE__ */ jsx140(Link, { href: "/waitlist", className: "text-primary underline", children: t("waitlist.invite.join_link") })
12324
+ ] }),
12325
+ /* @__PURE__ */ jsx140(CardFooter, { className: "flex w-full flex-row justify-between", children: /* @__PURE__ */ jsx140(Link, { href: "#", className: "flex w-full justify-start", onClick: () => setComponentType(0 /* Login */), children: t("auth.buttons.login") }) })
12326
+ ] });
12327
+ }
12244
12328
  return /* @__PURE__ */ jsxs81(Fragment20, { children: [
12245
12329
  /* @__PURE__ */ jsxs81(CardHeader, { children: [
12246
12330
  /* @__PURE__ */ jsxs81(CardTitle, { className: "text-primary flex flex-col items-center pb-10 text-4xl", children: [
@@ -12292,7 +12376,74 @@ function Register() {
12292
12376
  }
12293
12377
  ),
12294
12378
  /* @__PURE__ */ jsx140(GdprConsentSection, { form }),
12295
- /* @__PURE__ */ jsx140(Button, { className: "mt-4 w-full", type: "submit", children: t(`auth.buttons.register`) })
12379
+ /* @__PURE__ */ jsx140(Button, { className: "mt-4 w-full", type: "submit", children: t(`auth.buttons.register`) }),
12380
+ registrationMode === "waitlist" && inviteValidated && (isGoogleAuthEnabled() || isDiscordAuthEnabled()) && /* @__PURE__ */ jsxs81("div", { className: "space-y-4 pt-4", children: [
12381
+ /* @__PURE__ */ jsxs81("div", { className: "relative", children: [
12382
+ /* @__PURE__ */ jsx140("div", { className: "absolute inset-0 flex items-center", children: /* @__PURE__ */ jsx140("span", { className: "w-full border-t" }) }),
12383
+ /* @__PURE__ */ jsx140("div", { className: "relative flex justify-center text-xs uppercase", children: /* @__PURE__ */ jsx140("span", { className: "bg-card px-2 text-muted-foreground", children: t("auth.buttons.or") }) })
12384
+ ] }),
12385
+ /* @__PURE__ */ jsxs81("div", { className: "space-y-2", children: [
12386
+ isGoogleAuthEnabled() && /* @__PURE__ */ jsx140(
12387
+ Link,
12388
+ {
12389
+ href: `${getApiUrl()}auth/google${inviteCode ? `?invite=${inviteCode}` : ""}`,
12390
+ className: "flex w-full",
12391
+ children: /* @__PURE__ */ jsxs81(
12392
+ Button,
12393
+ {
12394
+ className: "w-full bg-white hover:bg-gray-50 text-gray-700 border border-gray-300",
12395
+ variant: "outline",
12396
+ type: "button",
12397
+ children: [
12398
+ /* @__PURE__ */ jsxs81("svg", { className: "mr-2 h-5 w-5", viewBox: "0 0 24 24", children: [
12399
+ /* @__PURE__ */ jsx140(
12400
+ "path",
12401
+ {
12402
+ fill: "#4285F4",
12403
+ d: "M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92c-.26 1.37-1.04 2.53-2.21 3.31v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.09z"
12404
+ }
12405
+ ),
12406
+ /* @__PURE__ */ jsx140(
12407
+ "path",
12408
+ {
12409
+ fill: "#34A853",
12410
+ d: "M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23z"
12411
+ }
12412
+ ),
12413
+ /* @__PURE__ */ jsx140(
12414
+ "path",
12415
+ {
12416
+ fill: "#FBBC05",
12417
+ d: "M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22.81-.62z"
12418
+ }
12419
+ ),
12420
+ /* @__PURE__ */ jsx140(
12421
+ "path",
12422
+ {
12423
+ fill: "#EA4335",
12424
+ d: "M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z"
12425
+ }
12426
+ )
12427
+ ] }),
12428
+ t("waitlist.buttons.register_with_google")
12429
+ ]
12430
+ }
12431
+ )
12432
+ }
12433
+ ),
12434
+ isDiscordAuthEnabled() && /* @__PURE__ */ jsx140(
12435
+ Link,
12436
+ {
12437
+ href: `${getApiUrl()}auth/discord${inviteCode ? `?invite=${inviteCode}` : ""}`,
12438
+ className: "flex w-full",
12439
+ children: /* @__PURE__ */ jsxs81(Button, { className: "w-full", variant: "outline", type: "button", children: [
12440
+ /* @__PURE__ */ jsx140("svg", { className: "mr-2 h-5 w-5", viewBox: "0 0 24 24", fill: "currentColor", children: /* @__PURE__ */ jsx140("path", { d: "M20.317 4.37a19.791 19.791 0 0 0-4.885-1.515.074.074 0 0 0-.079.037c-.21.375-.444.864-.608 1.25a18.27 18.27 0 0 0-5.487 0 12.64 12.64 0 0 0-.617-1.25.077.077 0 0 0-.079-.037A19.736 19.736 0 0 0 3.677 4.37a.07.07 0 0 0-.032.027C.533 9.046-.32 13.58.099 18.057a.082.082 0 0 0 .031.057 19.9 19.9 0 0 0 5.993 3.03.078.078 0 0 0 .084-.028 14.09 14.09 0 0 0 1.226-1.994.076.076 0 0 0-.041-.106 13.107 13.107 0 0 1-1.872-.892.077.077 0 0 1-.008-.128 10.2 10.2 0 0 0 .372-.292.074.074 0 0 1 .077-.01c3.928 1.793 8.18 1.793 12.062 0a.074.074 0 0 1 .078.01c.12.098.246.198.373.292a.077.077 0 0 1-.006.127 12.299 12.299 0 0 1-1.873.892.077.077 0 0 0-.041.107c.36.698.772 1.362 1.225 1.993a.076.076 0 0 0 .084.028 19.839 19.839 0 0 0 6.002-3.03.077.077 0 0 0 .032-.054c.5-5.177-.838-9.674-3.549-13.66a.061.061 0 0 0-.031-.03zM8.02 15.33c-1.183 0-2.157-1.085-2.157-2.419 0-1.333.956-2.419 2.157-2.419 1.21 0 2.176 1.096 2.157 2.42 0 1.333-.956 2.418-2.157 2.418zm7.975 0c-1.183 0-2.157-1.085-2.157-2.419 0-1.333.955-2.419 2.157-2.419 1.21 0 2.176 1.096 2.157 2.42 0 1.333-.946 2.418-2.157 2.418z" }) }),
12441
+ t("waitlist.buttons.register_with_discord")
12442
+ ] })
12443
+ }
12444
+ )
12445
+ ] })
12446
+ ] })
12296
12447
  ] }),
12297
12448
  /* @__PURE__ */ jsxs81(CardFooter, { className: "flex w-full flex-row justify-between", children: [
12298
12449
  /* @__PURE__ */ jsx140(
@@ -12474,7 +12625,7 @@ __name(LandingComponent, "LandingComponent");
12474
12625
  import { zodResolver as zodResolver5 } from "@hookform/resolvers/zod";
12475
12626
  import { useTranslations as useTranslations50 } from "next-intl";
12476
12627
  import Image10 from "next/image";
12477
- import { useEffect as useEffect40, useState as useState48 } from "react";
12628
+ import { useEffect as useEffect41, useState as useState48 } from "react";
12478
12629
  import { useForm as useForm5 } from "react-hook-form";
12479
12630
  import { z as z5 } from "zod";
12480
12631
  import { Fragment as Fragment22, jsx as jsx145, jsxs as jsxs84 } from "react/jsx-runtime";
@@ -12483,7 +12634,7 @@ function AcceptInvitation() {
12483
12634
  const [showConfirmation, setShowConfirmation] = useState48(false);
12484
12635
  const [error, setError] = useState48(void 0);
12485
12636
  const t = useTranslations50();
12486
- useEffect40(() => {
12637
+ useEffect41(() => {
12487
12638
  async function validateCode(code) {
12488
12639
  try {
12489
12640
  const payload = {
@@ -12576,14 +12727,14 @@ __name(AcceptInvitation, "AcceptInvitation");
12576
12727
  // src/features/auth/components/forms/ActivateAccount.tsx
12577
12728
  import { useTranslations as useTranslations51 } from "next-intl";
12578
12729
  import Image11 from "next/image";
12579
- import { useEffect as useEffect41, useState as useState49 } from "react";
12730
+ import { useEffect as useEffect42, useState as useState49 } from "react";
12580
12731
  import { Fragment as Fragment23, jsx as jsx146, jsxs as jsxs85 } from "react/jsx-runtime";
12581
12732
  function ActivateAccount() {
12582
12733
  const { setComponentType, params, setParams } = useAuthContext();
12583
12734
  const [showConfirmation, setShowConfirmation] = useState49(false);
12584
12735
  const [error, setError] = useState49(void 0);
12585
12736
  const t = useTranslations51();
12586
- useEffect41(() => {
12737
+ useEffect42(() => {
12587
12738
  async function ActivateAccount2(code) {
12588
12739
  try {
12589
12740
  const payload = {
@@ -12624,12 +12775,12 @@ function ActivateAccount() {
12624
12775
  __name(ActivateAccount, "ActivateAccount");
12625
12776
 
12626
12777
  // src/features/auth/components/forms/Cookies.tsx
12627
- import { useEffect as useEffect42, useState as useState50 } from "react";
12778
+ import { useEffect as useEffect43, useState as useState50 } from "react";
12628
12779
  function Cookies({ dehydratedAuth, page }) {
12629
12780
  const { setUser } = useCurrentUserContext();
12630
12781
  const router = useI18nRouter();
12631
12782
  const [hasSaved, setHasSaved] = useState50(false);
12632
- useEffect42(() => {
12783
+ useEffect43(() => {
12633
12784
  if (hasSaved) return;
12634
12785
  async function saveTokenOnServer() {
12635
12786
  await AuthService.saveToken({ dehydratedAuth });
@@ -12723,7 +12874,7 @@ __name(ForgotPassword, "ForgotPassword");
12723
12874
  import { zodResolver as zodResolver7 } from "@hookform/resolvers/zod";
12724
12875
  import { useTranslations as useTranslations53 } from "next-intl";
12725
12876
  import Image13 from "next/image";
12726
- import { useRouter, useSearchParams } from "next/navigation";
12877
+ import { useRouter, useSearchParams as useSearchParams2 } from "next/navigation";
12727
12878
  import { useForm as useForm7 } from "react-hook-form";
12728
12879
  import { z as z7 } from "zod";
12729
12880
  import { Fragment as Fragment25, jsx as jsx148, jsxs as jsxs87 } from "react/jsx-runtime";
@@ -12734,7 +12885,7 @@ function Login() {
12734
12885
  const generateUrl = usePageUrlGenerator();
12735
12886
  const i18nRouter = useI18nRouter();
12736
12887
  const nativeRouter = useRouter();
12737
- const searchParams = useSearchParams();
12888
+ const searchParams = useSearchParams2();
12738
12889
  const callbackUrl = searchParams.get("callbackUrl");
12739
12890
  const formSchema = z7.object({
12740
12891
  email: z7.string().email({
@@ -12832,11 +12983,11 @@ function Login() {
12832
12983
  __name(Login, "Login");
12833
12984
 
12834
12985
  // src/features/auth/components/forms/Logout.tsx
12835
- import { useEffect as useEffect43 } from "react";
12986
+ import { useEffect as useEffect44 } from "react";
12836
12987
  import { Fragment as Fragment26, jsx as jsx149 } from "react/jsx-runtime";
12837
12988
  function Logout() {
12838
12989
  const generateUrl = usePageUrlGenerator();
12839
- useEffect43(() => {
12990
+ useEffect44(() => {
12840
12991
  const logOut = /* @__PURE__ */ __name(async () => {
12841
12992
  await AuthService.logout();
12842
12993
  window.location.href = generateUrl({ page: `/` });
@@ -12849,7 +13000,7 @@ __name(Logout, "Logout");
12849
13000
 
12850
13001
  // src/features/auth/components/forms/RefreshUser.tsx
12851
13002
  import { deleteCookie, getCookie as getCookie2 } from "cookies-next";
12852
- import { useEffect as useEffect44 } from "react";
13003
+ import { useEffect as useEffect45 } from "react";
12853
13004
  function RefreshUser() {
12854
13005
  const { setUser } = useCurrentUserContext();
12855
13006
  const loadFullUser = /* @__PURE__ */ __name(async () => {
@@ -12869,7 +13020,7 @@ function RefreshUser() {
12869
13020
  deleteCookie("reloadData");
12870
13021
  }
12871
13022
  }, "loadFullUser");
12872
- useEffect44(() => {
13023
+ useEffect45(() => {
12873
13024
  const reloadData = getCookie2("reloadData");
12874
13025
  if (reloadData !== void 0) loadFullUser();
12875
13026
  }, []);
@@ -12881,7 +13032,7 @@ __name(RefreshUser, "RefreshUser");
12881
13032
  import { zodResolver as zodResolver8 } from "@hookform/resolvers/zod";
12882
13033
  import { useTranslations as useTranslations54 } from "next-intl";
12883
13034
  import Image14 from "next/image";
12884
- import { useEffect as useEffect45, useState as useState52 } from "react";
13035
+ import { useEffect as useEffect46, useState as useState52 } from "react";
12885
13036
  import { useForm as useForm8 } from "react-hook-form";
12886
13037
  import { z as z8 } from "zod";
12887
13038
  import { Fragment as Fragment27, jsx as jsx150, jsxs as jsxs88 } from "react/jsx-runtime";
@@ -12890,7 +13041,7 @@ function ResetPassword() {
12890
13041
  const [showConfirmation, setShowConfirmation] = useState52(false);
12891
13042
  const [error, setError] = useState52(void 0);
12892
13043
  const t = useTranslations54();
12893
- useEffect45(() => {
13044
+ useEffect46(() => {
12894
13045
  async function validateResetPasswordCode(code) {
12895
13046
  try {
12896
13047
  const payload = {
@@ -13172,7 +13323,7 @@ __name(NotificationsListContainer, "NotificationsListContainer");
13172
13323
  // src/features/notification/components/modals/NotificationModal.tsx
13173
13324
  import { BellIcon } from "lucide-react";
13174
13325
  import { useTranslations as useTranslations60 } from "next-intl";
13175
- import { Fragment as Fragment29, useCallback as useCallback22, useEffect as useEffect46, useMemo as useMemo21, useRef as useRef19, useState as useState53 } from "react";
13326
+ import { Fragment as Fragment29, useCallback as useCallback22, useEffect as useEffect47, useMemo as useMemo21, useRef as useRef19, useState as useState53 } from "react";
13176
13327
  import { jsx as jsx157, jsxs as jsxs93 } from "react/jsx-runtime";
13177
13328
  function NotificationModalContent({ isOpen, setIsOpen }) {
13178
13329
  const _instanceId = useRef19(Math.random().toString(36).substr(2, 9));
@@ -13224,10 +13375,10 @@ function NotificationModalContent({ isOpen, setIsOpen }) {
13224
13375
  unreadIds: unreadNotifications2.map((notif) => notif.id)
13225
13376
  };
13226
13377
  }, [notifications]);
13227
- useEffect46(() => {
13378
+ useEffect47(() => {
13228
13379
  setNewNotifications(unreadCount > 0);
13229
13380
  }, [unreadCount]);
13230
- useEffect46(() => {
13381
+ useEffect47(() => {
13231
13382
  if (lastLoaded === 0) loadNotifications();
13232
13383
  }, [lastLoaded, loadNotifications]);
13233
13384
  const processSocketNotificationsRef = useRef19(null);
@@ -13270,7 +13421,7 @@ function NotificationModalContent({ isOpen, setIsOpen }) {
13270
13421
  generateUrl,
13271
13422
  checkCircuitBreaker
13272
13423
  ]);
13273
- useEffect46(() => {
13424
+ useEffect47(() => {
13274
13425
  if (processSocketNotificationsRef.current) {
13275
13426
  clearTimeout(processSocketNotificationsRef.current);
13276
13427
  }
@@ -13404,13 +13555,13 @@ __name(FormRoles, "FormRoles");
13404
13555
 
13405
13556
  // src/features/role/components/forms/RemoveUserFromRole.tsx
13406
13557
  import { useTranslations as useTranslations63 } from "next-intl";
13407
- import { useEffect as useEffect47, useState as useState54 } from "react";
13558
+ import { useEffect as useEffect48, useState as useState54 } from "react";
13408
13559
  import { Fragment as Fragment32, jsx as jsx162, jsxs as jsxs96 } from "react/jsx-runtime";
13409
13560
  function RemoveUserFromRole({ role, user, refresh }) {
13410
13561
  const [open, setOpen] = useState54(false);
13411
13562
  const [canRemove, setCanRemove] = useState54(false);
13412
13563
  const t = useTranslations63();
13413
- useEffect47(() => {
13564
+ useEffect48(() => {
13414
13565
  async function checkCompanyAdminDeletability() {
13415
13566
  const roleUsers = await UserService.findAllUsersByRole({
13416
13567
  roleId: role.id
@@ -13480,7 +13631,7 @@ __name(RemoveUserFromRole, "RemoveUserFromRole");
13480
13631
  // src/features/role/components/forms/UserRoleAdd.tsx
13481
13632
  import { PlusCircle as PlusCircle2 } from "lucide-react";
13482
13633
  import { useTranslations as useTranslations64 } from "next-intl";
13483
- import { useCallback as useCallback23, useEffect as useEffect48, useRef as useRef20, useState as useState55 } from "react";
13634
+ import { useCallback as useCallback23, useEffect as useEffect49, useRef as useRef20, useState as useState55 } from "react";
13484
13635
  import { Fragment as Fragment33, jsx as jsx163, jsxs as jsxs97 } from "react/jsx-runtime";
13485
13636
  function UserRoleAdd({ user, refresh }) {
13486
13637
  const [open, setOpen] = useState55(false);
@@ -13522,10 +13673,10 @@ function UserRoleAdd({ user, refresh }) {
13522
13673
  [searchTerm, user]
13523
13674
  );
13524
13675
  const updateSearchTerm = useDebounce(searchRoles, 500);
13525
- useEffect48(() => {
13676
+ useEffect49(() => {
13526
13677
  if (open) updateSearchTerm(searchTerm);
13527
13678
  }, [open, searchTerm]);
13528
- useEffect48(() => {
13679
+ useEffect49(() => {
13529
13680
  if (open) searchRoles("");
13530
13681
  }, [open]);
13531
13682
  return /* @__PURE__ */ jsxs97(Fragment33, { children: [
@@ -14351,7 +14502,7 @@ function OAuthConsentActions({ onApprove, onDeny, isLoading = false }) {
14351
14502
  __name(OAuthConsentActions, "OAuthConsentActions");
14352
14503
 
14353
14504
  // src/features/oauth/components/consent/OAuthConsentScreen.tsx
14354
- import { ExternalLink as ExternalLink2, AlertTriangle as AlertTriangle2, Loader2 as Loader23 } from "lucide-react";
14505
+ import { ExternalLink as ExternalLink2, AlertTriangle as AlertTriangle2, Loader2 as Loader24 } from "lucide-react";
14355
14506
  import { jsx as jsx176, jsxs as jsxs108 } from "react/jsx-runtime";
14356
14507
  function OAuthConsentScreen({
14357
14508
  params,
@@ -14363,7 +14514,7 @@ function OAuthConsentScreen({
14363
14514
  const { clientInfo, isLoading, error, approve, deny, isSubmitting } = useOAuthConsent(params);
14364
14515
  if (isLoading) {
14365
14516
  return /* @__PURE__ */ jsx176("div", { className: "min-h-screen flex items-center justify-center p-4", children: /* @__PURE__ */ jsx176(Card, { className: "w-full max-w-md", children: /* @__PURE__ */ jsxs108(CardContent, { className: "flex flex-col items-center justify-center py-12", children: [
14366
- /* @__PURE__ */ jsx176(Loader23, { className: "h-8 w-8 animate-spin text-muted-foreground" }),
14517
+ /* @__PURE__ */ jsx176(Loader24, { className: "h-8 w-8 animate-spin text-muted-foreground" }),
14367
14518
  /* @__PURE__ */ jsx176("p", { className: "mt-4 text-muted-foreground", children: "Loading authorization request..." })
14368
14519
  ] }) }) });
14369
14520
  }
@@ -14403,6 +14554,504 @@ function OAuthConsentScreen({
14403
14554
  }
14404
14555
  __name(OAuthConsentScreen, "OAuthConsentScreen");
14405
14556
 
14557
+ // src/features/waitlist/components/forms/WaitlistForm.tsx
14558
+ import { zodResolver as zodResolver9 } from "@hookform/resolvers/zod";
14559
+ import { CheckCircle, Mail } from "lucide-react";
14560
+ import { useTranslations as useTranslations67 } from "next-intl";
14561
+ import { useState as useState59 } from "react";
14562
+ import { useForm as useForm9 } from "react-hook-form";
14563
+ import { v4 as v45 } from "uuid";
14564
+ import { z as z9 } from "zod";
14565
+
14566
+ // src/features/waitlist/components/forms/WaitlistQuestionnaireRenderer.tsx
14567
+ import { jsx as jsx177, jsxs as jsxs109 } from "react/jsx-runtime";
14568
+ function WaitlistQuestionnaireRenderer({
14569
+ form,
14570
+ fields,
14571
+ fieldPrefix = "questionnaire"
14572
+ }) {
14573
+ if (!fields || fields.length === 0) {
14574
+ return null;
14575
+ }
14576
+ return /* @__PURE__ */ jsx177("div", { className: "space-y-4", children: fields.map((field) => {
14577
+ const fieldId = `${fieldPrefix}.${field.id}`;
14578
+ switch (field.type) {
14579
+ case "text":
14580
+ return /* @__PURE__ */ jsx177(
14581
+ FormInput,
14582
+ {
14583
+ form,
14584
+ id: fieldId,
14585
+ name: field.label,
14586
+ placeholder: field.placeholder,
14587
+ isRequired: field.required
14588
+ },
14589
+ field.id
14590
+ );
14591
+ case "textarea":
14592
+ return /* @__PURE__ */ jsx177(
14593
+ FormTextarea,
14594
+ {
14595
+ form,
14596
+ id: fieldId,
14597
+ name: field.label,
14598
+ placeholder: field.placeholder,
14599
+ className: "min-h-24"
14600
+ },
14601
+ field.id
14602
+ );
14603
+ case "select":
14604
+ if (!field.options || field.options.length === 0) {
14605
+ return null;
14606
+ }
14607
+ return /* @__PURE__ */ jsx177(
14608
+ FormSelect,
14609
+ {
14610
+ form,
14611
+ id: fieldId,
14612
+ name: field.label,
14613
+ values: field.options.map((opt) => ({
14614
+ id: opt.value,
14615
+ text: opt.label
14616
+ }))
14617
+ },
14618
+ field.id
14619
+ );
14620
+ case "checkbox":
14621
+ if (!field.options || field.options.length === 0) {
14622
+ return /* @__PURE__ */ jsx177(
14623
+ FormCheckbox,
14624
+ {
14625
+ form,
14626
+ id: fieldId,
14627
+ name: field.label,
14628
+ description: field.description,
14629
+ isRequired: field.required
14630
+ },
14631
+ field.id
14632
+ );
14633
+ }
14634
+ return /* @__PURE__ */ jsxs109("div", { className: "space-y-2", children: [
14635
+ /* @__PURE__ */ jsxs109("span", { className: "text-sm font-medium", children: [
14636
+ field.label,
14637
+ field.required && /* @__PURE__ */ jsx177("span", { className: "text-destructive ml-1", children: "*" })
14638
+ ] }),
14639
+ field.description && /* @__PURE__ */ jsx177("p", { className: "text-muted-foreground text-xs", children: field.description }),
14640
+ /* @__PURE__ */ jsx177("div", { className: "space-y-2", children: field.options.map((option) => /* @__PURE__ */ jsx177(
14641
+ FormCheckbox,
14642
+ {
14643
+ form,
14644
+ id: `${fieldId}.${option.value}`,
14645
+ name: option.label,
14646
+ description: option.description
14647
+ },
14648
+ option.value
14649
+ )) })
14650
+ ] }, field.id);
14651
+ default:
14652
+ return null;
14653
+ }
14654
+ }) });
14655
+ }
14656
+ __name(WaitlistQuestionnaireRenderer, "WaitlistQuestionnaireRenderer");
14657
+
14658
+ // src/features/waitlist/components/forms/WaitlistForm.tsx
14659
+ import { Fragment as Fragment35, jsx as jsx178, jsxs as jsxs110 } from "react/jsx-runtime";
14660
+ function WaitlistForm({ onSuccess }) {
14661
+ const t = useTranslations67();
14662
+ const [isSubmitting, setIsSubmitting] = useState59(false);
14663
+ const [isSuccess, setIsSuccess] = useState59(false);
14664
+ const config = getWaitlistConfig();
14665
+ const questionnaireFields = config.questionnaire ?? [];
14666
+ const questionnaireSchema = questionnaireFields.reduce(
14667
+ (acc, field) => {
14668
+ if (field.type === "checkbox" && field.options && field.options.length > 0) {
14669
+ const optionsSchema = field.options.reduce(
14670
+ (optAcc, opt) => {
14671
+ optAcc[opt.value] = z9.boolean().optional();
14672
+ return optAcc;
14673
+ },
14674
+ {}
14675
+ );
14676
+ acc[field.id] = z9.object(optionsSchema).optional();
14677
+ } else if (field.type === "checkbox") {
14678
+ acc[field.id] = field.required ? z9.literal(true) : z9.boolean().optional();
14679
+ } else if (field.type === "select") {
14680
+ acc[field.id] = field.required ? z9.string().min(1) : z9.string().optional();
14681
+ } else {
14682
+ acc[field.id] = field.required ? z9.string().min(1) : z9.string().optional();
14683
+ }
14684
+ return acc;
14685
+ },
14686
+ {}
14687
+ );
14688
+ const formSchema = z9.object({
14689
+ id: z9.uuidv4(),
14690
+ email: z9.email({ message: t("common.errors.invalid_email") }),
14691
+ gdprConsent: z9.literal(true, {
14692
+ message: t("auth.gdpr.terms_required")
14693
+ }),
14694
+ marketingConsent: z9.boolean().optional(),
14695
+ questionnaire: z9.object(questionnaireSchema).optional()
14696
+ });
14697
+ const questionnaireDefaults = questionnaireFields.reduce(
14698
+ (acc, field) => {
14699
+ if (field.type === "checkbox" && field.options && field.options.length > 0) {
14700
+ acc[field.id] = field.options.reduce(
14701
+ (optAcc, opt) => {
14702
+ optAcc[opt.value] = false;
14703
+ return optAcc;
14704
+ },
14705
+ {}
14706
+ );
14707
+ } else if (field.type === "checkbox") {
14708
+ acc[field.id] = false;
14709
+ } else {
14710
+ acc[field.id] = "";
14711
+ }
14712
+ return acc;
14713
+ },
14714
+ {}
14715
+ );
14716
+ const form = useForm9({
14717
+ resolver: zodResolver9(formSchema),
14718
+ defaultValues: {
14719
+ id: v45(),
14720
+ email: "",
14721
+ gdprConsent: false,
14722
+ marketingConsent: false,
14723
+ questionnaire: questionnaireDefaults
14724
+ }
14725
+ });
14726
+ const onSubmit = /* @__PURE__ */ __name(async (values) => {
14727
+ setIsSubmitting(true);
14728
+ try {
14729
+ const now = (/* @__PURE__ */ new Date()).toISOString();
14730
+ await WaitlistService.submit({
14731
+ id: values.id,
14732
+ email: values.email,
14733
+ gdprConsent: values.gdprConsent,
14734
+ gdprConsentAt: now,
14735
+ marketingConsent: values.marketingConsent ?? false,
14736
+ marketingConsentAt: values.marketingConsent ? now : void 0,
14737
+ questionnaire: values.questionnaire
14738
+ });
14739
+ setIsSuccess(true);
14740
+ onSuccess?.();
14741
+ } catch (e) {
14742
+ errorToast({ error: e });
14743
+ } finally {
14744
+ setIsSubmitting(false);
14745
+ }
14746
+ }, "onSubmit");
14747
+ if (isSuccess) {
14748
+ return /* @__PURE__ */ jsxs110("div", { className: "space-y-6 text-center", children: [
14749
+ /* @__PURE__ */ jsx178("div", { className: "mx-auto flex h-16 w-16 items-center justify-center rounded-full bg-green-100", children: /* @__PURE__ */ jsx178(CheckCircle, { className: "h-8 w-8 text-green-600" }) }),
14750
+ /* @__PURE__ */ jsxs110("div", { className: "space-y-2", children: [
14751
+ /* @__PURE__ */ jsx178("h3", { className: "text-xl font-semibold", children: t("waitlist.success.title") }),
14752
+ /* @__PURE__ */ jsx178("p", { className: "text-muted-foreground", children: t("waitlist.success.description") })
14753
+ ] }),
14754
+ /* @__PURE__ */ jsxs110("div", { className: "flex items-center justify-center gap-2 text-muted-foreground text-sm", children: [
14755
+ /* @__PURE__ */ jsx178(Mail, { className: "h-4 w-4" }),
14756
+ /* @__PURE__ */ jsx178("span", { children: t("waitlist.success.hint") })
14757
+ ] })
14758
+ ] });
14759
+ }
14760
+ return /* @__PURE__ */ jsx178(Form, { ...form, children: /* @__PURE__ */ jsxs110("form", { onSubmit: form.handleSubmit(onSubmit), className: "space-y-4", children: [
14761
+ /* @__PURE__ */ jsx178(
14762
+ FormInput,
14763
+ {
14764
+ isRequired: true,
14765
+ form,
14766
+ id: "email",
14767
+ name: t("common.fields.email.label"),
14768
+ placeholder: t("common.fields.email.placeholder")
14769
+ }
14770
+ ),
14771
+ questionnaireFields.length > 0 && /* @__PURE__ */ jsx178(WaitlistQuestionnaireRenderer, { form, fields: questionnaireFields }),
14772
+ /* @__PURE__ */ jsxs110("div", { className: "space-y-4 py-4", children: [
14773
+ /* @__PURE__ */ jsx178(
14774
+ GdprConsentCheckbox,
14775
+ {
14776
+ form,
14777
+ id: "gdprConsent",
14778
+ label: /* @__PURE__ */ jsxs110(Fragment35, { children: [
14779
+ t("auth.gdpr.terms_prefix"),
14780
+ /* @__PURE__ */ jsx178(Link, { href: "/terms", target: "_blank", rel: "noopener", className: "underline", children: t("auth.gdpr.terms_of_service") }),
14781
+ t("auth.gdpr.and"),
14782
+ /* @__PURE__ */ jsx178(Link, { href: "/privacy", target: "_blank", rel: "noopener", className: "underline", children: t("auth.gdpr.privacy_policy") })
14783
+ ] }),
14784
+ required: true
14785
+ }
14786
+ ),
14787
+ /* @__PURE__ */ jsx178(
14788
+ GdprConsentCheckbox,
14789
+ {
14790
+ form,
14791
+ id: "marketingConsent",
14792
+ label: t("auth.gdpr.marketing_consent"),
14793
+ description: t("auth.gdpr.marketing_description")
14794
+ }
14795
+ )
14796
+ ] }),
14797
+ /* @__PURE__ */ jsx178(Button, { type: "submit", className: "w-full", disabled: isSubmitting, children: isSubmitting ? t("common.actions.submitting") : t("waitlist.buttons.join") })
14798
+ ] }) });
14799
+ }
14800
+ __name(WaitlistForm, "WaitlistForm");
14801
+
14802
+ // src/features/waitlist/components/sections/WaitlistHeroSection.tsx
14803
+ import { CheckCircle as CheckCircle2 } from "lucide-react";
14804
+ import { jsx as jsx179, jsxs as jsxs111 } from "react/jsx-runtime";
14805
+ function WaitlistHeroSection() {
14806
+ const config = getWaitlistConfig();
14807
+ return /* @__PURE__ */ jsx179("section", { className: "relative overflow-hidden py-16 md:py-24", children: /* @__PURE__ */ jsx179("div", { className: "container mx-auto px-4", children: /* @__PURE__ */ jsxs111("div", { className: "grid gap-12 lg:grid-cols-2 lg:items-center", children: [
14808
+ /* @__PURE__ */ jsxs111("div", { className: "space-y-8", children: [
14809
+ /* @__PURE__ */ jsxs111("div", { className: "space-y-4", children: [
14810
+ config.heroTitle && /* @__PURE__ */ jsx179("h1", { className: "text-4xl font-bold tracking-tight md:text-5xl lg:text-6xl", children: config.heroTitle }),
14811
+ config.heroSubtitle && /* @__PURE__ */ jsx179("p", { className: "text-muted-foreground text-xl md:text-2xl", children: config.heroSubtitle }),
14812
+ config.heroDescription && /* @__PURE__ */ jsx179("p", { className: "text-muted-foreground", children: config.heroDescription })
14813
+ ] }),
14814
+ config.benefits && config.benefits.length > 0 && /* @__PURE__ */ jsx179("ul", { className: "space-y-3", children: config.benefits.map((benefit, index) => /* @__PURE__ */ jsxs111("li", { className: "flex items-start gap-3", children: [
14815
+ /* @__PURE__ */ jsx179(CheckCircle2, { className: "text-primary mt-0.5 h-5 w-5 shrink-0" }),
14816
+ /* @__PURE__ */ jsx179("span", { children: benefit })
14817
+ ] }, index)) })
14818
+ ] }),
14819
+ /* @__PURE__ */ jsx179("div", { className: "lg:pl-8", children: /* @__PURE__ */ jsx179("div", { className: "bg-card rounded-lg border p-6 shadow-lg md:p-8", children: /* @__PURE__ */ jsx179(WaitlistForm, {}) }) })
14820
+ ] }) }) });
14821
+ }
14822
+ __name(WaitlistHeroSection, "WaitlistHeroSection");
14823
+
14824
+ // src/features/waitlist/components/sections/WaitlistSuccessState.tsx
14825
+ import { CheckCircle as CheckCircle3 } from "lucide-react";
14826
+ import { useTranslations as useTranslations68 } from "next-intl";
14827
+ import { jsx as jsx180, jsxs as jsxs112 } from "react/jsx-runtime";
14828
+ function WaitlistSuccessState() {
14829
+ const t = useTranslations68();
14830
+ return /* @__PURE__ */ jsxs112("div", { className: "flex flex-col items-center justify-center space-y-4 py-8 text-center", children: [
14831
+ /* @__PURE__ */ jsx180("div", { className: "bg-primary/10 rounded-full p-4", children: /* @__PURE__ */ jsx180(CheckCircle3, { className: "text-primary h-12 w-12" }) }),
14832
+ /* @__PURE__ */ jsx180("h2", { className: "text-2xl font-bold", children: t("waitlist.success.title") }),
14833
+ /* @__PURE__ */ jsx180("p", { className: "text-muted-foreground max-w-md", children: t("waitlist.success.description") }),
14834
+ /* @__PURE__ */ jsx180("p", { className: "text-muted-foreground text-sm", children: t("waitlist.success.hint") })
14835
+ ] });
14836
+ }
14837
+ __name(WaitlistSuccessState, "WaitlistSuccessState");
14838
+
14839
+ // src/features/waitlist/components/sections/WaitlistConfirmation.tsx
14840
+ import { CheckCircle as CheckCircle4, Loader2 as Loader25, XCircle as XCircle2 } from "lucide-react";
14841
+ import { useTranslations as useTranslations69 } from "next-intl";
14842
+ import { useEffect as useEffect50, useState as useState60 } from "react";
14843
+ import { jsx as jsx181, jsxs as jsxs113 } from "react/jsx-runtime";
14844
+ function WaitlistConfirmation({ code }) {
14845
+ const t = useTranslations69();
14846
+ const [state, setState] = useState60("loading");
14847
+ const [errorMessage, setErrorMessage] = useState60("");
14848
+ useEffect50(() => {
14849
+ async function confirmEmail() {
14850
+ try {
14851
+ await WaitlistService.confirm(code);
14852
+ setState("success");
14853
+ } catch (error) {
14854
+ setState("error");
14855
+ setErrorMessage(error instanceof Error ? error.message : t("waitlist.confirmation.error_default"));
14856
+ }
14857
+ }
14858
+ __name(confirmEmail, "confirmEmail");
14859
+ confirmEmail();
14860
+ }, [code, t]);
14861
+ if (state === "loading") {
14862
+ return /* @__PURE__ */ jsxs113("div", { className: "flex flex-col items-center justify-center space-y-4 py-16 text-center", children: [
14863
+ /* @__PURE__ */ jsx181(Loader25, { className: "text-primary h-12 w-12 animate-spin" }),
14864
+ /* @__PURE__ */ jsx181("p", { className: "text-muted-foreground", children: t("waitlist.confirmation.loading") })
14865
+ ] });
14866
+ }
14867
+ if (state === "error") {
14868
+ return /* @__PURE__ */ jsxs113("div", { className: "flex flex-col items-center justify-center space-y-4 py-16 text-center", children: [
14869
+ /* @__PURE__ */ jsx181("div", { className: "bg-destructive/10 rounded-full p-4", children: /* @__PURE__ */ jsx181(XCircle2, { className: "text-destructive h-12 w-12" }) }),
14870
+ /* @__PURE__ */ jsx181("h2", { className: "text-2xl font-bold", children: t("waitlist.confirmation.error_title") }),
14871
+ /* @__PURE__ */ jsx181("p", { className: "text-muted-foreground max-w-md", children: errorMessage }),
14872
+ /* @__PURE__ */ jsx181(Link, { href: "/waitlist", className: buttonVariants({ variant: "outline" }), children: t("waitlist.buttons.return") })
14873
+ ] });
14874
+ }
14875
+ return /* @__PURE__ */ jsxs113("div", { className: "flex flex-col items-center justify-center space-y-4 py-16 text-center", children: [
14876
+ /* @__PURE__ */ jsx181("div", { className: "bg-primary/10 rounded-full p-4", children: /* @__PURE__ */ jsx181(CheckCircle4, { className: "text-primary h-12 w-12" }) }),
14877
+ /* @__PURE__ */ jsx181("h2", { className: "text-2xl font-bold", children: t("waitlist.confirmation.success_title") }),
14878
+ /* @__PURE__ */ jsx181("p", { className: "text-muted-foreground max-w-md", children: t("waitlist.confirmation.success_description") }),
14879
+ /* @__PURE__ */ jsx181("p", { className: "text-muted-foreground text-sm", children: t("waitlist.confirmation.success_hint") })
14880
+ ] });
14881
+ }
14882
+ __name(WaitlistConfirmation, "WaitlistConfirmation");
14883
+
14884
+ // src/features/waitlist/components/lists/WaitlistList.tsx
14885
+ import { flexRender as flexRender2, getCoreRowModel as getCoreRowModel2, useReactTable as useReactTable2 } from "@tanstack/react-table";
14886
+ import { RefreshCw as RefreshCw3, Users } from "lucide-react";
14887
+ import { useTranslations as useTranslations71 } from "next-intl";
14888
+ import { useCallback as useCallback29, useEffect as useEffect51, useState as useState61 } from "react";
14889
+
14890
+ // src/features/waitlist/hooks/useWaitlistTableStructure.tsx
14891
+ import { Send } from "lucide-react";
14892
+ import { useTranslations as useTranslations70 } from "next-intl";
14893
+ import { jsx as jsx182, jsxs as jsxs114 } from "react/jsx-runtime";
14894
+ function parseQuestionnaire(questionnaire) {
14895
+ if (!questionnaire) return null;
14896
+ try {
14897
+ return JSON.parse(questionnaire);
14898
+ } catch {
14899
+ return null;
14900
+ }
14901
+ }
14902
+ __name(parseQuestionnaire, "parseQuestionnaire");
14903
+ function useWaitlistTableStructure({
14904
+ onInvite
14905
+ }) {
14906
+ const t = useTranslations70();
14907
+ const getStatusBadge = /* @__PURE__ */ __name((status) => {
14908
+ const variants = {
14909
+ pending: { variant: "secondary" },
14910
+ confirmed: { variant: "default" },
14911
+ invited: { variant: "outline" },
14912
+ registered: { variant: "default" }
14913
+ };
14914
+ const config = variants[status];
14915
+ return /* @__PURE__ */ jsx182(Badge, { variant: config.variant, children: t(`waitlist.admin.status.${status}`) });
14916
+ }, "getStatusBadge");
14917
+ return [
14918
+ {
14919
+ accessorKey: "email",
14920
+ header: t("waitlist.admin.columns.email"),
14921
+ cell: /* @__PURE__ */ __name(({ row }) => /* @__PURE__ */ jsx182("span", { className: "font-medium", children: row.original.email }), "cell")
14922
+ },
14923
+ {
14924
+ accessorKey: "status",
14925
+ header: t("waitlist.admin.columns.status"),
14926
+ cell: /* @__PURE__ */ __name(({ row }) => getStatusBadge(row.original.status), "cell")
14927
+ },
14928
+ {
14929
+ accessorKey: "createdAt",
14930
+ header: t("waitlist.admin.columns.submitted"),
14931
+ cell: /* @__PURE__ */ __name(({ row }) => {
14932
+ if (!row.original.createdAt) return "-";
14933
+ return new Date(row.original.createdAt).toLocaleDateString();
14934
+ }, "cell")
14935
+ },
14936
+ {
14937
+ accessorKey: "questionnaire",
14938
+ header: t("waitlist.admin.columns.questionnaire"),
14939
+ cell: /* @__PURE__ */ __name(({ row }) => {
14940
+ const questionnaire = parseQuestionnaire(row.original.questionnaire);
14941
+ if (!questionnaire || Object.keys(questionnaire).length === 0) {
14942
+ return /* @__PURE__ */ jsx182("span", { className: "text-muted-foreground", children: "-" });
14943
+ }
14944
+ return /* @__PURE__ */ jsxs114("details", { className: "cursor-pointer", children: [
14945
+ /* @__PURE__ */ jsx182("summary", { className: "text-primary text-sm", children: t("waitlist.admin.questionnaire.view_answers") }),
14946
+ /* @__PURE__ */ jsx182("div", { className: "bg-muted mt-2 rounded p-2 text-sm", children: Object.entries(questionnaire).map(([key, value]) => /* @__PURE__ */ jsxs114("div", { className: "mb-1", children: [
14947
+ /* @__PURE__ */ jsxs114("span", { className: "font-medium", children: [
14948
+ key,
14949
+ ":"
14950
+ ] }),
14951
+ " ",
14952
+ /* @__PURE__ */ jsx182("span", { className: "text-muted-foreground", children: Array.isArray(value) ? value.join(", ") : String(value) })
14953
+ ] }, key)) })
14954
+ ] });
14955
+ }, "cell")
14956
+ },
14957
+ {
14958
+ id: "actions",
14959
+ header: t("waitlist.admin.columns.actions"),
14960
+ cell: /* @__PURE__ */ __name(({ row }) => {
14961
+ const entry = row.original;
14962
+ if (entry.status === "confirmed") {
14963
+ return /* @__PURE__ */ jsxs114(Button, { size: "sm", variant: "outline", onClick: () => onInvite(entry), children: [
14964
+ /* @__PURE__ */ jsx182(Send, { className: "mr-2 h-4 w-4" }),
14965
+ t("waitlist.admin.actions.invite")
14966
+ ] });
14967
+ }
14968
+ if (entry.status === "invited" && entry.invitedAt) {
14969
+ return /* @__PURE__ */ jsx182("span", { className: "text-muted-foreground text-sm", children: t("waitlist.admin.actions.invited_on", { date: new Date(entry.invitedAt).toLocaleDateString() }) });
14970
+ }
14971
+ if (entry.status === "registered") {
14972
+ return /* @__PURE__ */ jsx182("span", { className: "text-muted-foreground text-sm", children: t("waitlist.admin.actions.registered") });
14973
+ }
14974
+ return /* @__PURE__ */ jsx182("span", { className: "text-muted-foreground text-sm", children: t("waitlist.admin.actions.awaiting_confirmation") });
14975
+ }, "cell")
14976
+ }
14977
+ ];
14978
+ }
14979
+ __name(useWaitlistTableStructure, "useWaitlistTableStructure");
14980
+
14981
+ // src/features/waitlist/components/lists/WaitlistList.tsx
14982
+ import { jsx as jsx183, jsxs as jsxs115 } from "react/jsx-runtime";
14983
+ function WaitlistList() {
14984
+ const t = useTranslations71();
14985
+ const [entries, setEntries] = useState61([]);
14986
+ const [total, setTotal] = useState61(0);
14987
+ const [isLoading, setIsLoading] = useState61(true);
14988
+ const [statusFilter, setStatusFilter] = useState61("all");
14989
+ const loadEntries = useCallback29(async () => {
14990
+ setIsLoading(true);
14991
+ try {
14992
+ const result = await WaitlistService.findMany({
14993
+ status: statusFilter === "all" ? void 0 : statusFilter,
14994
+ fetchAll: true
14995
+ });
14996
+ setEntries(result);
14997
+ setTotal(result.length);
14998
+ } catch (error) {
14999
+ errorToast({ error });
15000
+ } finally {
15001
+ setIsLoading(false);
15002
+ }
15003
+ }, [statusFilter]);
15004
+ useEffect51(() => {
15005
+ loadEntries();
15006
+ }, [loadEntries]);
15007
+ const handleInvite = /* @__PURE__ */ __name(async (entry) => {
15008
+ try {
15009
+ await WaitlistService.invite(entry.id);
15010
+ showToast(t("waitlist.admin.invite_sent", { email: entry.email }));
15011
+ loadEntries();
15012
+ } catch (error) {
15013
+ errorToast({ error });
15014
+ }
15015
+ }, "handleInvite");
15016
+ const columns = useWaitlistTableStructure({ onInvite: handleInvite });
15017
+ const table = useReactTable2({
15018
+ data: entries,
15019
+ columns,
15020
+ getCoreRowModel: getCoreRowModel2()
15021
+ });
15022
+ return /* @__PURE__ */ jsxs115("div", { className: "space-y-4", children: [
15023
+ /* @__PURE__ */ jsxs115("div", { className: "flex items-center justify-between", children: [
15024
+ /* @__PURE__ */ jsxs115("div", { className: "flex items-center gap-2", children: [
15025
+ /* @__PURE__ */ jsx183(Users, { className: "h-5 w-5" }),
15026
+ /* @__PURE__ */ jsx183("h2", { className: "text-xl font-semibold", children: t("waitlist.admin.title") }),
15027
+ /* @__PURE__ */ jsxs115("span", { className: "text-muted-foreground", children: [
15028
+ "(",
15029
+ t("waitlist.admin.entries_count", { count: total }),
15030
+ ")"
15031
+ ] })
15032
+ ] }),
15033
+ /* @__PURE__ */ jsxs115("div", { className: "flex items-center gap-4", children: [
15034
+ /* @__PURE__ */ jsxs115(Select, { value: statusFilter, onValueChange: (value) => setStatusFilter(value ?? "all"), children: [
15035
+ /* @__PURE__ */ jsx183(SelectTrigger, { className: "w-40", children: /* @__PURE__ */ jsx183(SelectValue, { placeholder: t("waitlist.admin.filter_placeholder") }) }),
15036
+ /* @__PURE__ */ jsxs115(SelectContent, { children: [
15037
+ /* @__PURE__ */ jsx183(SelectItem, { value: "all", children: t("waitlist.admin.all_statuses") }),
15038
+ /* @__PURE__ */ jsx183(SelectItem, { value: "pending", children: t("waitlist.admin.status.pending") }),
15039
+ /* @__PURE__ */ jsx183(SelectItem, { value: "confirmed", children: t("waitlist.admin.status.confirmed") }),
15040
+ /* @__PURE__ */ jsx183(SelectItem, { value: "invited", children: t("waitlist.admin.status.invited") }),
15041
+ /* @__PURE__ */ jsx183(SelectItem, { value: "registered", children: t("waitlist.admin.status.registered") })
15042
+ ] })
15043
+ ] }),
15044
+ /* @__PURE__ */ jsx183(Button, { variant: "outline", size: "icon", onClick: loadEntries, disabled: isLoading, children: /* @__PURE__ */ jsx183(RefreshCw3, { className: `h-4 w-4 ${isLoading ? "animate-spin" : ""}` }) })
15045
+ ] })
15046
+ ] }),
15047
+ /* @__PURE__ */ jsx183("div", { className: "rounded-md border", children: /* @__PURE__ */ jsxs115(Table, { children: [
15048
+ /* @__PURE__ */ jsx183(TableHeader, { children: table.getHeaderGroups().map((headerGroup) => /* @__PURE__ */ jsx183(TableRow, { children: headerGroup.headers.map((header) => /* @__PURE__ */ jsx183(TableHead, { children: header.isPlaceholder ? null : flexRender2(header.column.columnDef.header, header.getContext()) }, header.id)) }, headerGroup.id)) }),
15049
+ /* @__PURE__ */ jsx183(TableBody, { children: isLoading ? /* @__PURE__ */ jsx183(TableRow, { children: /* @__PURE__ */ jsx183(TableCell, { colSpan: columns.length, className: "h-24 text-center", children: t("waitlist.admin.loading") }) }) : entries.length === 0 ? /* @__PURE__ */ jsx183(TableRow, { children: /* @__PURE__ */ jsx183(TableCell, { colSpan: columns.length, className: "h-24 text-center", children: t("waitlist.admin.empty") }) }) : table.getRowModel().rows.map((row) => /* @__PURE__ */ jsx183(TableRow, { children: row.getVisibleCells().map((cell) => /* @__PURE__ */ jsx183(TableCell, { children: flexRender2(cell.column.columnDef.cell, cell.getContext()) }, cell.id)) }, row.id)) })
15050
+ ] }) })
15051
+ ] });
15052
+ }
15053
+ __name(WaitlistList, "WaitlistList");
15054
+
14406
15055
  export {
14407
15056
  JsonApiProvider,
14408
15057
  useJsonApiGet,
@@ -14799,6 +15448,12 @@ export {
14799
15448
  OAuthConsentActions,
14800
15449
  useOAuthConsent,
14801
15450
  OAuthConsentScreen,
15451
+ WaitlistQuestionnaireRenderer,
15452
+ WaitlistForm,
15453
+ WaitlistHeroSection,
15454
+ WaitlistSuccessState,
15455
+ WaitlistConfirmation,
15456
+ WaitlistList,
14802
15457
  AddUserToRole,
14803
15458
  UserAvatarEditor,
14804
15459
  UserDeleter,
@@ -14826,4 +15481,4 @@ export {
14826
15481
  useOAuthClients,
14827
15482
  useOAuthClient
14828
15483
  };
14829
- //# sourceMappingURL=chunk-LDH2FGJY.mjs.map
15484
+ //# sourceMappingURL=chunk-BAOP6PTD.mjs.map