@open-mercato/onboarding 0.6.1-develop.3278.1.a4d26475e4 → 0.6.1-develop.3287.1.450f4ffb56

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.
@@ -12,6 +12,8 @@ import { Button } from "@open-mercato/ui/primitives/button";
12
12
  import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@open-mercato/ui/primitives/card";
13
13
  import { Checkbox } from "@open-mercato/ui/primitives/checkbox";
14
14
  import { Input } from "@open-mercato/ui/primitives/input";
15
+ import { EmailInput } from "@open-mercato/ui/primitives/email-input";
16
+ import { PasswordInput } from "@open-mercato/ui/primitives/password-input";
15
17
  import { Label } from "@open-mercato/ui/primitives/label";
16
18
  function OnboardingPageClient({ onboardingEnabled }) {
17
19
  const t = useT();
@@ -160,14 +162,12 @@ function OnboardingPageClient({ onboardingEnabled }) {
160
162
  /* @__PURE__ */ jsxs("div", { className: "grid gap-1", children: [
161
163
  /* @__PURE__ */ jsx(Label, { htmlFor: "email", children: translate("onboarding.form.email", "Work email") }),
162
164
  /* @__PURE__ */ jsx(
163
- Input,
165
+ EmailInput,
164
166
  {
165
167
  id: "email",
166
168
  name: "email",
167
- type: "email",
168
169
  required: true,
169
170
  disabled,
170
- autoComplete: "email",
171
171
  "aria-invalid": Boolean(fieldErrors.email),
172
172
  "aria-describedby": fieldErrors.email ? "email-error" : void 0,
173
173
  className: fieldErrors.email ? "border-red-500 aria-invalid:ring-destructive" : void 0
@@ -234,11 +234,10 @@ function OnboardingPageClient({ onboardingEnabled }) {
234
234
  /* @__PURE__ */ jsxs("div", { className: "grid gap-1", children: [
235
235
  /* @__PURE__ */ jsx(Label, { htmlFor: "password", children: translate("onboarding.form.password", "Password") }),
236
236
  /* @__PURE__ */ jsx(
237
- Input,
237
+ PasswordInput,
238
238
  {
239
239
  id: "password",
240
240
  name: "password",
241
- type: "password",
242
241
  required: true,
243
242
  disabled,
244
243
  autoComplete: "new-password",
@@ -254,11 +253,10 @@ function OnboardingPageClient({ onboardingEnabled }) {
254
253
  /* @__PURE__ */ jsxs("div", { className: "grid gap-1", children: [
255
254
  /* @__PURE__ */ jsx(Label, { htmlFor: "confirmPassword", children: translate("onboarding.form.confirmPassword", "Confirm password") }),
256
255
  /* @__PURE__ */ jsx(
257
- Input,
256
+ PasswordInput,
258
257
  {
259
258
  id: "confirmPassword",
260
259
  name: "confirmPassword",
261
- type: "password",
262
260
  required: true,
263
261
  disabled,
264
262
  autoComplete: "new-password",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../src/modules/onboarding/frontend/onboarding/OnboardingPageClient.tsx"],
4
- "sourcesContent": ["'use client'\n\nimport Image from 'next/image'\nimport Link from 'next/link'\nimport { useState } from 'react'\nimport { useLocale, useT } from '@open-mercato/shared/lib/i18n/context'\nimport { translateWithFallback } from '@open-mercato/shared/lib/i18n/translate'\nimport { formatPasswordRequirements, getPasswordPolicy } from '@open-mercato/shared/lib/auth/passwordPolicy'\nimport { onboardingStartSchema } from '@open-mercato/onboarding/modules/onboarding/data/validators'\nimport { apiCall } from '@open-mercato/ui/backend/utils/apiCall'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@open-mercato/ui/primitives/card'\nimport { Checkbox } from '@open-mercato/ui/primitives/checkbox'\nimport { Input } from '@open-mercato/ui/primitives/input'\nimport { Label } from '@open-mercato/ui/primitives/label'\n\ntype SubmissionState = 'idle' | 'loading' | 'success'\ntype FieldErrors = Partial<Record<\n 'email' | 'firstName' | 'lastName' | 'organizationName' | 'password' | 'confirmPassword' | 'termsAccepted' | 'marketingConsent',\n string\n>>\n\ntype Props = {\n onboardingEnabled: boolean\n}\n\nexport default function OnboardingPageClient({ onboardingEnabled }: Props) {\n const t = useT()\n const translate = (key: string, fallback: string, params?: Record<string, string | number>) =>\n translateWithFallback(t, key, fallback, params)\n const locale = useLocale()\n const [state, setState] = useState<SubmissionState>('idle')\n const [globalError, setGlobalError] = useState<string | null>(null)\n const [fieldErrors, setFieldErrors] = useState<FieldErrors>({})\n const [termsAccepted, setTermsAccepted] = useState(false)\n const [marketingConsent, setMarketingConsent] = useState(false)\n const [emailSubmitted, setEmailSubmitted] = useState<string | null>(null)\n const passwordPolicy = getPasswordPolicy()\n const passwordRequirements = formatPasswordRequirements(passwordPolicy, translate, 'onboarding.password.requirements')\n const passwordDescription = passwordRequirements\n ? translate(\n 'onboarding.password.requirements.help',\n 'Password requirements: {requirements}',\n { requirements: passwordRequirements },\n )\n : ''\n\n async function onSubmit(event: React.FormEvent<HTMLFormElement>) {\n event.preventDefault()\n if (!onboardingEnabled) return\n\n setState('loading')\n setGlobalError(null)\n setFieldErrors({})\n\n const form = new FormData(event.currentTarget)\n const payload = {\n email: String(form.get('email') ?? '').trim(),\n firstName: String(form.get('firstName') ?? '').trim(),\n lastName: String(form.get('lastName') ?? '').trim(),\n organizationName: String(form.get('organizationName') ?? '').trim(),\n password: String(form.get('password') ?? ''),\n confirmPassword: String(form.get('confirmPassword') ?? ''),\n termsAccepted,\n marketingConsent,\n locale,\n }\n\n const parsed = onboardingStartSchema.safeParse(payload)\n if (!parsed.success) {\n const issueMap: FieldErrors = {}\n parsed.error.issues.forEach((issue) => {\n const path = issue.path[0]\n if (!path) return\n switch (path) {\n case 'email':\n issueMap.email = translate('onboarding.errors.emailInvalid', 'Enter a valid work email.')\n break\n case 'firstName':\n issueMap.firstName = translate('onboarding.errors.firstNameRequired', 'First name is required.')\n break\n case 'lastName':\n issueMap.lastName = translate('onboarding.errors.lastNameRequired', 'Last name is required.')\n break\n case 'organizationName':\n issueMap.organizationName = translate('onboarding.errors.organizationNameRequired', 'Organization name is required.')\n break\n case 'password':\n issueMap.password = translate(\n 'onboarding.errors.passwordRequired',\n 'Password must meet the requirements: {requirements}.',\n { requirements: passwordRequirements },\n )\n break\n case 'confirmPassword':\n issueMap.confirmPassword = translate('onboarding.errors.passwordMismatch', 'Passwords must match.')\n break\n case 'termsAccepted':\n issueMap.termsAccepted = translate('onboarding.form.termsRequired', 'Please accept the terms to continue.')\n break\n default:\n break\n }\n })\n if (!issueMap.termsAccepted && !termsAccepted) {\n issueMap.termsAccepted = translate('onboarding.form.termsRequired', 'Please accept the terms to continue.')\n }\n setFieldErrors(issueMap)\n setState('idle')\n return\n }\n\n try {\n const call = await apiCall<{ ok?: boolean; error?: string; email?: string; fieldErrors?: Record<string, string> }>(\n '/api/onboarding/onboarding',\n {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ ...parsed.data, termsAccepted: true, marketingConsent }),\n },\n )\n const data = call.result ?? {}\n if (!call.ok || data.ok === false) {\n if (data.fieldErrors && typeof data.fieldErrors === 'object') {\n const mapped: FieldErrors = {}\n for (const key of Object.keys(data.fieldErrors)) {\n const value = data.fieldErrors[key]\n if (typeof value === 'string' && value.trim()) {\n mapped[key as keyof FieldErrors] = value\n }\n }\n setFieldErrors(mapped)\n }\n const message = typeof data.error === 'string' && data.error.trim()\n ? data.error\n : translate('onboarding.form.genericError', 'Something went wrong. Please try again.')\n setGlobalError(message)\n setState('idle')\n return\n }\n setEmailSubmitted(data.email ?? parsed.data.email)\n setState('success')\n } catch (err) {\n const message = err instanceof Error ? err.message : ''\n setGlobalError(message || translate('onboarding.form.genericError', 'Something went wrong. Please try again.'))\n setState('idle')\n }\n }\n\n const onboardingDisabled = !onboardingEnabled\n const submitting = state === 'loading'\n const disabled = onboardingDisabled || submitting || state === 'success'\n\n return (\n <div className=\"relative flex min-h-svh items-center justify-center bg-muted/50 px-4 pb-24\">\n <Card className=\"relative w-full max-w-lg overflow-hidden shadow-lg\">\n {onboardingDisabled ? (\n <div className=\"absolute inset-0 z-10 flex items-center justify-center rounded-lg bg-background/80 p-6 backdrop-blur-[2px]\">\n <div\n className=\"max-w-sm rounded-xl border border-border/70 bg-background/95 px-5 py-4 text-center shadow-sm\"\n role=\"alert\"\n aria-live=\"polite\"\n >\n <p className=\"text-base font-semibold text-foreground\">\n {translate('onboarding.disabled.title', 'Self-service onboarding is currently unavailable')}\n </p>\n <p className=\"mt-2 text-sm text-muted-foreground\">\n {translate(\n 'onboarding.disabled.description',\n 'Workspace creation is currently handled manually. Contact the Open Mercato team or your administrator to request access before continuing.',\n )}\n </p>\n <div className=\"mt-4 flex justify-center\">\n <Button asChild variant=\"outline\">\n <Link href=\"/login\">\n {translate('onboarding.disabled.cta', 'Go to login')}\n </Link>\n </Button>\n </div>\n </div>\n </div>\n ) : null}\n <CardHeader className=\"flex flex-col gap-4 p-10 text-center\">\n <div className=\"flex flex-col items-center gap-3\">\n <Image alt=\"Open Mercato\" src=\"/open-mercato.svg\" width={120} height={120} priority />\n <CardTitle className=\"text-2xl font-semibold\">\n {translate('onboarding.title', 'Create your Open Mercato workspace')}\n </CardTitle>\n <CardDescription>\n {translate('onboarding.subtitle', 'Tell us a bit about you and we will set everything up.')}\n </CardDescription>\n </div>\n </CardHeader>\n <CardContent className={onboardingDisabled ? 'pb-10 opacity-45' : 'pb-10'}>\n {state === 'success' && emailSubmitted && (\n <div className=\"mb-6 rounded-md border border-emerald-200 bg-emerald-50 px-4 py-3 text-sm text-emerald-900\" role=\"status\" aria-live=\"polite\">\n <strong className=\"block text-sm font-medium\">\n {translate('onboarding.form.successTitle', 'Check your inbox')}\n </strong>\n <p>\n {translate('onboarding.form.successBody', 'We sent a verification link to {email}. Confirm it within 24 hours to activate your workspace.', { email: emailSubmitted })}\n </p>\n </div>\n )}\n {state !== 'success' && globalError && (\n <div className=\"mb-4 rounded-md border border-red-200 bg-red-50 px-4 py-3 text-sm text-red-700\" role=\"alert\" aria-live=\"assertive\">\n {globalError}\n </div>\n )}\n <form className=\"grid gap-4\" onSubmit={onSubmit} noValidate>\n <div className=\"grid gap-1\">\n <Label htmlFor=\"email\">{translate('onboarding.form.email', 'Work email')}</Label>\n <Input\n id=\"email\"\n name=\"email\"\n type=\"email\"\n required\n disabled={disabled}\n autoComplete=\"email\"\n aria-invalid={Boolean(fieldErrors.email)}\n aria-describedby={fieldErrors.email ? 'email-error' : undefined}\n className={fieldErrors.email ? 'border-red-500 aria-invalid:ring-destructive' : undefined}\n />\n {fieldErrors.email && (\n <p id=\"email-error\" className=\"text-xs text-red-600\">{fieldErrors.email}</p>\n )}\n </div>\n <div className=\"grid gap-1 sm:grid-cols-2 sm:gap-4\">\n <div className=\"grid gap-1\">\n <Label htmlFor=\"firstName\">{translate('onboarding.form.firstName', 'First name')}</Label>\n <Input\n id=\"firstName\"\n name=\"firstName\"\n type=\"text\"\n required\n disabled={disabled}\n autoComplete=\"given-name\"\n aria-invalid={Boolean(fieldErrors.firstName)}\n aria-describedby={fieldErrors.firstName ? 'firstName-error' : undefined}\n className={fieldErrors.firstName ? 'border-red-500 aria-invalid:ring-destructive' : undefined}\n />\n {fieldErrors.firstName && (\n <p id=\"firstName-error\" className=\"text-xs text-red-600\">{fieldErrors.firstName}</p>\n )}\n </div>\n <div className=\"grid gap-1\">\n <Label htmlFor=\"lastName\">{translate('onboarding.form.lastName', 'Last name')}</Label>\n <Input\n id=\"lastName\"\n name=\"lastName\"\n type=\"text\"\n required\n disabled={disabled}\n autoComplete=\"family-name\"\n aria-invalid={Boolean(fieldErrors.lastName)}\n aria-describedby={fieldErrors.lastName ? 'lastName-error' : undefined}\n className={fieldErrors.lastName ? 'border-red-500 aria-invalid:ring-destructive' : undefined}\n />\n {fieldErrors.lastName && (\n <p id=\"lastName-error\" className=\"text-xs text-red-600\">{fieldErrors.lastName}</p>\n )}\n </div>\n </div>\n <div className=\"grid gap-1\">\n <Label htmlFor=\"organizationName\">{translate('onboarding.form.organizationName', 'Organization name')}</Label>\n <Input\n id=\"organizationName\"\n name=\"organizationName\"\n type=\"text\"\n required\n disabled={disabled}\n autoComplete=\"organization\"\n aria-invalid={Boolean(fieldErrors.organizationName)}\n aria-describedby={fieldErrors.organizationName ? 'organizationName-error' : undefined}\n className={fieldErrors.organizationName ? 'border-red-500 aria-invalid:ring-destructive' : undefined}\n />\n {fieldErrors.organizationName && (\n <p id=\"organizationName-error\" className=\"text-xs text-red-600\">{fieldErrors.organizationName}</p>\n )}\n </div>\n <div className=\"grid gap-1\">\n <Label htmlFor=\"password\">{translate('onboarding.form.password', 'Password')}</Label>\n <Input\n id=\"password\"\n name=\"password\"\n type=\"password\"\n required\n disabled={disabled}\n autoComplete=\"new-password\"\n minLength={passwordPolicy.minLength}\n aria-invalid={Boolean(fieldErrors.password)}\n aria-describedby={fieldErrors.password ? 'password-error' : undefined}\n className={fieldErrors.password ? 'border-red-500 aria-invalid:ring-destructive' : undefined}\n />\n {passwordDescription ? (\n <p className=\"text-xs text-muted-foreground\">{passwordDescription}</p>\n ) : null}\n {fieldErrors.password && (\n <p id=\"password-error\" className=\"text-xs text-red-600\">{fieldErrors.password}</p>\n )}\n </div>\n <div className=\"grid gap-1\">\n <Label htmlFor=\"confirmPassword\">{translate('onboarding.form.confirmPassword', 'Confirm password')}</Label>\n <Input\n id=\"confirmPassword\"\n name=\"confirmPassword\"\n type=\"password\"\n required\n disabled={disabled}\n autoComplete=\"new-password\"\n aria-invalid={Boolean(fieldErrors.confirmPassword)}\n aria-describedby={fieldErrors.confirmPassword ? 'confirmPassword-error' : undefined}\n className={fieldErrors.confirmPassword ? 'border-red-500 aria-invalid:ring-destructive' : undefined}\n />\n {fieldErrors.confirmPassword && (\n <p id=\"confirmPassword-error\" className=\"text-xs text-red-600\">{fieldErrors.confirmPassword}</p>\n )}\n </div>\n <label className=\"flex items-start gap-3 text-sm text-muted-foreground\">\n <Checkbox\n id=\"terms\"\n checked={termsAccepted}\n disabled={disabled}\n onCheckedChange={(value: boolean | 'indeterminate') => {\n setTermsAccepted(value === true)\n if (value === true) {\n setFieldErrors((prev) => {\n const next = { ...prev }\n delete next.termsAccepted\n return next\n })\n }\n }}\n aria-invalid={Boolean(fieldErrors.termsAccepted)}\n />\n <span>\n {translate('onboarding.form.termsLabel', 'I have read and accept the ')}\n <a className=\"underline hover:text-foreground\" href=\"/terms\" target=\"_blank\" rel=\"noreferrer\">\n {translate('onboarding.form.termsLink', 'Terms of Service')}\n </a>\n {translate('onboarding.form.termsAnd', ' and ')}\n <a className=\"underline hover:text-foreground\" href=\"/privacy\" target=\"_blank\" rel=\"noreferrer\">\n {translate('onboarding.form.privacyLink', 'Privacy Policy')}\n </a>\n {fieldErrors.termsAccepted && (\n <span className=\"mt-1 block text-xs text-red-600\">{fieldErrors.termsAccepted}</span>\n )}\n </span>\n </label>\n <label className=\"flex items-start gap-3 text-sm text-muted-foreground\">\n <Checkbox\n id=\"marketingConsent\"\n checked={marketingConsent}\n disabled={disabled}\n onCheckedChange={(value: boolean | 'indeterminate') => {\n setMarketingConsent(value === true)\n }}\n />\n <span>\n {translate(\n 'onboarding.form.marketingLabel',\n \"I consent to receiving direct marketing from CT Tornado by email at the address I provide. I'm aware that I can withdraw my consent at any time (e.g., via the unsubscribe link), and that CT Tornado may also process my email address under its legitimate interests to manage its mailing list, keep proof of my consent, and record opt-outs. See our {termsLink} and {privacyLink}.\",\n )\n .split(/{termsLink}|{privacyLink}/)\n .map((part, index, parts) => (\n <span key={index}>\n {part}\n {index < parts.length - 1 && (\n index === 0 ? (\n <a className=\"underline hover:text-foreground\" href=\"/terms\" target=\"_blank\" rel=\"noreferrer\">\n {translate('onboarding.form.termsLink', 'Terms of Service')}\n </a>\n ) : (\n <a className=\"underline hover:text-foreground\" href=\"/privacy\" target=\"_blank\" rel=\"noreferrer\">\n {translate('onboarding.form.privacyLink', 'Privacy Policy')}\n </a>\n )\n )}\n </span>\n ))}\n </span>\n </label>\n <Button\n type=\"submit\"\n disabled={disabled}\n className=\"mt-2 h-11 bg-foreground text-background transition hover:opacity-80 disabled:cursor-not-allowed disabled:opacity-50\"\n >\n {submitting\n ? translate('onboarding.form.loading', 'Sending...')\n : translate('onboarding.form.submit', 'Send verification email')}\n </Button>\n </form>\n </CardContent>\n </Card>\n </div>\n )\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["'use client'\n\nimport Image from 'next/image'\nimport Link from 'next/link'\nimport { useState } from 'react'\nimport { useLocale, useT } from '@open-mercato/shared/lib/i18n/context'\nimport { translateWithFallback } from '@open-mercato/shared/lib/i18n/translate'\nimport { formatPasswordRequirements, getPasswordPolicy } from '@open-mercato/shared/lib/auth/passwordPolicy'\nimport { onboardingStartSchema } from '@open-mercato/onboarding/modules/onboarding/data/validators'\nimport { apiCall } from '@open-mercato/ui/backend/utils/apiCall'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@open-mercato/ui/primitives/card'\nimport { Checkbox } from '@open-mercato/ui/primitives/checkbox'\nimport { Input } from '@open-mercato/ui/primitives/input'\nimport { EmailInput } from '@open-mercato/ui/primitives/email-input'\nimport { PasswordInput } from '@open-mercato/ui/primitives/password-input'\nimport { Label } from '@open-mercato/ui/primitives/label'\n\ntype SubmissionState = 'idle' | 'loading' | 'success'\ntype FieldErrors = Partial<Record<\n 'email' | 'firstName' | 'lastName' | 'organizationName' | 'password' | 'confirmPassword' | 'termsAccepted' | 'marketingConsent',\n string\n>>\n\ntype Props = {\n onboardingEnabled: boolean\n}\n\nexport default function OnboardingPageClient({ onboardingEnabled }: Props) {\n const t = useT()\n const translate = (key: string, fallback: string, params?: Record<string, string | number>) =>\n translateWithFallback(t, key, fallback, params)\n const locale = useLocale()\n const [state, setState] = useState<SubmissionState>('idle')\n const [globalError, setGlobalError] = useState<string | null>(null)\n const [fieldErrors, setFieldErrors] = useState<FieldErrors>({})\n const [termsAccepted, setTermsAccepted] = useState(false)\n const [marketingConsent, setMarketingConsent] = useState(false)\n const [emailSubmitted, setEmailSubmitted] = useState<string | null>(null)\n const passwordPolicy = getPasswordPolicy()\n const passwordRequirements = formatPasswordRequirements(passwordPolicy, translate, 'onboarding.password.requirements')\n const passwordDescription = passwordRequirements\n ? translate(\n 'onboarding.password.requirements.help',\n 'Password requirements: {requirements}',\n { requirements: passwordRequirements },\n )\n : ''\n\n async function onSubmit(event: React.FormEvent<HTMLFormElement>) {\n event.preventDefault()\n if (!onboardingEnabled) return\n\n setState('loading')\n setGlobalError(null)\n setFieldErrors({})\n\n const form = new FormData(event.currentTarget)\n const payload = {\n email: String(form.get('email') ?? '').trim(),\n firstName: String(form.get('firstName') ?? '').trim(),\n lastName: String(form.get('lastName') ?? '').trim(),\n organizationName: String(form.get('organizationName') ?? '').trim(),\n password: String(form.get('password') ?? ''),\n confirmPassword: String(form.get('confirmPassword') ?? ''),\n termsAccepted,\n marketingConsent,\n locale,\n }\n\n const parsed = onboardingStartSchema.safeParse(payload)\n if (!parsed.success) {\n const issueMap: FieldErrors = {}\n parsed.error.issues.forEach((issue) => {\n const path = issue.path[0]\n if (!path) return\n switch (path) {\n case 'email':\n issueMap.email = translate('onboarding.errors.emailInvalid', 'Enter a valid work email.')\n break\n case 'firstName':\n issueMap.firstName = translate('onboarding.errors.firstNameRequired', 'First name is required.')\n break\n case 'lastName':\n issueMap.lastName = translate('onboarding.errors.lastNameRequired', 'Last name is required.')\n break\n case 'organizationName':\n issueMap.organizationName = translate('onboarding.errors.organizationNameRequired', 'Organization name is required.')\n break\n case 'password':\n issueMap.password = translate(\n 'onboarding.errors.passwordRequired',\n 'Password must meet the requirements: {requirements}.',\n { requirements: passwordRequirements },\n )\n break\n case 'confirmPassword':\n issueMap.confirmPassword = translate('onboarding.errors.passwordMismatch', 'Passwords must match.')\n break\n case 'termsAccepted':\n issueMap.termsAccepted = translate('onboarding.form.termsRequired', 'Please accept the terms to continue.')\n break\n default:\n break\n }\n })\n if (!issueMap.termsAccepted && !termsAccepted) {\n issueMap.termsAccepted = translate('onboarding.form.termsRequired', 'Please accept the terms to continue.')\n }\n setFieldErrors(issueMap)\n setState('idle')\n return\n }\n\n try {\n const call = await apiCall<{ ok?: boolean; error?: string; email?: string; fieldErrors?: Record<string, string> }>(\n '/api/onboarding/onboarding',\n {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ ...parsed.data, termsAccepted: true, marketingConsent }),\n },\n )\n const data = call.result ?? {}\n if (!call.ok || data.ok === false) {\n if (data.fieldErrors && typeof data.fieldErrors === 'object') {\n const mapped: FieldErrors = {}\n for (const key of Object.keys(data.fieldErrors)) {\n const value = data.fieldErrors[key]\n if (typeof value === 'string' && value.trim()) {\n mapped[key as keyof FieldErrors] = value\n }\n }\n setFieldErrors(mapped)\n }\n const message = typeof data.error === 'string' && data.error.trim()\n ? data.error\n : translate('onboarding.form.genericError', 'Something went wrong. Please try again.')\n setGlobalError(message)\n setState('idle')\n return\n }\n setEmailSubmitted(data.email ?? parsed.data.email)\n setState('success')\n } catch (err) {\n const message = err instanceof Error ? err.message : ''\n setGlobalError(message || translate('onboarding.form.genericError', 'Something went wrong. Please try again.'))\n setState('idle')\n }\n }\n\n const onboardingDisabled = !onboardingEnabled\n const submitting = state === 'loading'\n const disabled = onboardingDisabled || submitting || state === 'success'\n\n return (\n <div className=\"relative flex min-h-svh items-center justify-center bg-muted/50 px-4 pb-24\">\n <Card className=\"relative w-full max-w-lg overflow-hidden shadow-lg\">\n {onboardingDisabled ? (\n <div className=\"absolute inset-0 z-10 flex items-center justify-center rounded-lg bg-background/80 p-6 backdrop-blur-[2px]\">\n <div\n className=\"max-w-sm rounded-xl border border-border/70 bg-background/95 px-5 py-4 text-center shadow-sm\"\n role=\"alert\"\n aria-live=\"polite\"\n >\n <p className=\"text-base font-semibold text-foreground\">\n {translate('onboarding.disabled.title', 'Self-service onboarding is currently unavailable')}\n </p>\n <p className=\"mt-2 text-sm text-muted-foreground\">\n {translate(\n 'onboarding.disabled.description',\n 'Workspace creation is currently handled manually. Contact the Open Mercato team or your administrator to request access before continuing.',\n )}\n </p>\n <div className=\"mt-4 flex justify-center\">\n <Button asChild variant=\"outline\">\n <Link href=\"/login\">\n {translate('onboarding.disabled.cta', 'Go to login')}\n </Link>\n </Button>\n </div>\n </div>\n </div>\n ) : null}\n <CardHeader className=\"flex flex-col gap-4 p-10 text-center\">\n <div className=\"flex flex-col items-center gap-3\">\n <Image alt=\"Open Mercato\" src=\"/open-mercato.svg\" width={120} height={120} priority />\n <CardTitle className=\"text-2xl font-semibold\">\n {translate('onboarding.title', 'Create your Open Mercato workspace')}\n </CardTitle>\n <CardDescription>\n {translate('onboarding.subtitle', 'Tell us a bit about you and we will set everything up.')}\n </CardDescription>\n </div>\n </CardHeader>\n <CardContent className={onboardingDisabled ? 'pb-10 opacity-45' : 'pb-10'}>\n {state === 'success' && emailSubmitted && (\n <div className=\"mb-6 rounded-md border border-emerald-200 bg-emerald-50 px-4 py-3 text-sm text-emerald-900\" role=\"status\" aria-live=\"polite\">\n <strong className=\"block text-sm font-medium\">\n {translate('onboarding.form.successTitle', 'Check your inbox')}\n </strong>\n <p>\n {translate('onboarding.form.successBody', 'We sent a verification link to {email}. Confirm it within 24 hours to activate your workspace.', { email: emailSubmitted })}\n </p>\n </div>\n )}\n {state !== 'success' && globalError && (\n <div className=\"mb-4 rounded-md border border-red-200 bg-red-50 px-4 py-3 text-sm text-red-700\" role=\"alert\" aria-live=\"assertive\">\n {globalError}\n </div>\n )}\n <form className=\"grid gap-4\" onSubmit={onSubmit} noValidate>\n <div className=\"grid gap-1\">\n <Label htmlFor=\"email\">{translate('onboarding.form.email', 'Work email')}</Label>\n <EmailInput\n id=\"email\"\n name=\"email\"\n required\n disabled={disabled}\n aria-invalid={Boolean(fieldErrors.email)}\n aria-describedby={fieldErrors.email ? 'email-error' : undefined}\n className={fieldErrors.email ? 'border-red-500 aria-invalid:ring-destructive' : undefined}\n />\n {fieldErrors.email && (\n <p id=\"email-error\" className=\"text-xs text-red-600\">{fieldErrors.email}</p>\n )}\n </div>\n <div className=\"grid gap-1 sm:grid-cols-2 sm:gap-4\">\n <div className=\"grid gap-1\">\n <Label htmlFor=\"firstName\">{translate('onboarding.form.firstName', 'First name')}</Label>\n <Input\n id=\"firstName\"\n name=\"firstName\"\n type=\"text\"\n required\n disabled={disabled}\n autoComplete=\"given-name\"\n aria-invalid={Boolean(fieldErrors.firstName)}\n aria-describedby={fieldErrors.firstName ? 'firstName-error' : undefined}\n className={fieldErrors.firstName ? 'border-red-500 aria-invalid:ring-destructive' : undefined}\n />\n {fieldErrors.firstName && (\n <p id=\"firstName-error\" className=\"text-xs text-red-600\">{fieldErrors.firstName}</p>\n )}\n </div>\n <div className=\"grid gap-1\">\n <Label htmlFor=\"lastName\">{translate('onboarding.form.lastName', 'Last name')}</Label>\n <Input\n id=\"lastName\"\n name=\"lastName\"\n type=\"text\"\n required\n disabled={disabled}\n autoComplete=\"family-name\"\n aria-invalid={Boolean(fieldErrors.lastName)}\n aria-describedby={fieldErrors.lastName ? 'lastName-error' : undefined}\n className={fieldErrors.lastName ? 'border-red-500 aria-invalid:ring-destructive' : undefined}\n />\n {fieldErrors.lastName && (\n <p id=\"lastName-error\" className=\"text-xs text-red-600\">{fieldErrors.lastName}</p>\n )}\n </div>\n </div>\n <div className=\"grid gap-1\">\n <Label htmlFor=\"organizationName\">{translate('onboarding.form.organizationName', 'Organization name')}</Label>\n <Input\n id=\"organizationName\"\n name=\"organizationName\"\n type=\"text\"\n required\n disabled={disabled}\n autoComplete=\"organization\"\n aria-invalid={Boolean(fieldErrors.organizationName)}\n aria-describedby={fieldErrors.organizationName ? 'organizationName-error' : undefined}\n className={fieldErrors.organizationName ? 'border-red-500 aria-invalid:ring-destructive' : undefined}\n />\n {fieldErrors.organizationName && (\n <p id=\"organizationName-error\" className=\"text-xs text-red-600\">{fieldErrors.organizationName}</p>\n )}\n </div>\n <div className=\"grid gap-1\">\n <Label htmlFor=\"password\">{translate('onboarding.form.password', 'Password')}</Label>\n <PasswordInput\n id=\"password\"\n name=\"password\"\n required\n disabled={disabled}\n autoComplete=\"new-password\"\n minLength={passwordPolicy.minLength}\n aria-invalid={Boolean(fieldErrors.password)}\n aria-describedby={fieldErrors.password ? 'password-error' : undefined}\n className={fieldErrors.password ? 'border-red-500 aria-invalid:ring-destructive' : undefined}\n />\n {passwordDescription ? (\n <p className=\"text-xs text-muted-foreground\">{passwordDescription}</p>\n ) : null}\n {fieldErrors.password && (\n <p id=\"password-error\" className=\"text-xs text-red-600\">{fieldErrors.password}</p>\n )}\n </div>\n <div className=\"grid gap-1\">\n <Label htmlFor=\"confirmPassword\">{translate('onboarding.form.confirmPassword', 'Confirm password')}</Label>\n <PasswordInput\n id=\"confirmPassword\"\n name=\"confirmPassword\"\n required\n disabled={disabled}\n autoComplete=\"new-password\"\n aria-invalid={Boolean(fieldErrors.confirmPassword)}\n aria-describedby={fieldErrors.confirmPassword ? 'confirmPassword-error' : undefined}\n className={fieldErrors.confirmPassword ? 'border-red-500 aria-invalid:ring-destructive' : undefined}\n />\n {fieldErrors.confirmPassword && (\n <p id=\"confirmPassword-error\" className=\"text-xs text-red-600\">{fieldErrors.confirmPassword}</p>\n )}\n </div>\n <label className=\"flex items-start gap-3 text-sm text-muted-foreground\">\n <Checkbox\n id=\"terms\"\n checked={termsAccepted}\n disabled={disabled}\n onCheckedChange={(value: boolean | 'indeterminate') => {\n setTermsAccepted(value === true)\n if (value === true) {\n setFieldErrors((prev) => {\n const next = { ...prev }\n delete next.termsAccepted\n return next\n })\n }\n }}\n aria-invalid={Boolean(fieldErrors.termsAccepted)}\n />\n <span>\n {translate('onboarding.form.termsLabel', 'I have read and accept the ')}\n <a className=\"underline hover:text-foreground\" href=\"/terms\" target=\"_blank\" rel=\"noreferrer\">\n {translate('onboarding.form.termsLink', 'Terms of Service')}\n </a>\n {translate('onboarding.form.termsAnd', ' and ')}\n <a className=\"underline hover:text-foreground\" href=\"/privacy\" target=\"_blank\" rel=\"noreferrer\">\n {translate('onboarding.form.privacyLink', 'Privacy Policy')}\n </a>\n {fieldErrors.termsAccepted && (\n <span className=\"mt-1 block text-xs text-red-600\">{fieldErrors.termsAccepted}</span>\n )}\n </span>\n </label>\n <label className=\"flex items-start gap-3 text-sm text-muted-foreground\">\n <Checkbox\n id=\"marketingConsent\"\n checked={marketingConsent}\n disabled={disabled}\n onCheckedChange={(value: boolean | 'indeterminate') => {\n setMarketingConsent(value === true)\n }}\n />\n <span>\n {translate(\n 'onboarding.form.marketingLabel',\n \"I consent to receiving direct marketing from CT Tornado by email at the address I provide. I'm aware that I can withdraw my consent at any time (e.g., via the unsubscribe link), and that CT Tornado may also process my email address under its legitimate interests to manage its mailing list, keep proof of my consent, and record opt-outs. See our {termsLink} and {privacyLink}.\",\n )\n .split(/{termsLink}|{privacyLink}/)\n .map((part, index, parts) => (\n <span key={index}>\n {part}\n {index < parts.length - 1 && (\n index === 0 ? (\n <a className=\"underline hover:text-foreground\" href=\"/terms\" target=\"_blank\" rel=\"noreferrer\">\n {translate('onboarding.form.termsLink', 'Terms of Service')}\n </a>\n ) : (\n <a className=\"underline hover:text-foreground\" href=\"/privacy\" target=\"_blank\" rel=\"noreferrer\">\n {translate('onboarding.form.privacyLink', 'Privacy Policy')}\n </a>\n )\n )}\n </span>\n ))}\n </span>\n </label>\n <Button\n type=\"submit\"\n disabled={disabled}\n className=\"mt-2 h-11 bg-foreground text-background transition hover:opacity-80 disabled:cursor-not-allowed disabled:opacity-50\"\n >\n {submitting\n ? translate('onboarding.form.loading', 'Sending...')\n : translate('onboarding.form.submit', 'Send verification email')}\n </Button>\n </form>\n </CardContent>\n </Card>\n </div>\n )\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@open-mercato/onboarding",
3
- "version": "0.6.1-develop.3278.1.a4d26475e4",
3
+ "version": "0.6.1-develop.3287.1.450f4ffb56",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "scripts": {
@@ -69,10 +69,10 @@
69
69
  }
70
70
  },
71
71
  "peerDependencies": {
72
- "@open-mercato/shared": "0.6.1-develop.3278.1.a4d26475e4"
72
+ "@open-mercato/shared": "0.6.1-develop.3287.1.450f4ffb56"
73
73
  },
74
74
  "devDependencies": {
75
- "@open-mercato/shared": "0.6.1-develop.3278.1.a4d26475e4",
75
+ "@open-mercato/shared": "0.6.1-develop.3287.1.450f4ffb56",
76
76
  "@types/jest": "^30.0.0",
77
77
  "jest": "^30.4.2",
78
78
  "ts-jest": "^29.4.9"
@@ -12,6 +12,8 @@ import { Button } from '@open-mercato/ui/primitives/button'
12
12
  import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@open-mercato/ui/primitives/card'
13
13
  import { Checkbox } from '@open-mercato/ui/primitives/checkbox'
14
14
  import { Input } from '@open-mercato/ui/primitives/input'
15
+ import { EmailInput } from '@open-mercato/ui/primitives/email-input'
16
+ import { PasswordInput } from '@open-mercato/ui/primitives/password-input'
15
17
  import { Label } from '@open-mercato/ui/primitives/label'
16
18
 
17
19
  type SubmissionState = 'idle' | 'loading' | 'success'
@@ -210,13 +212,11 @@ export default function OnboardingPageClient({ onboardingEnabled }: Props) {
210
212
  <form className="grid gap-4" onSubmit={onSubmit} noValidate>
211
213
  <div className="grid gap-1">
212
214
  <Label htmlFor="email">{translate('onboarding.form.email', 'Work email')}</Label>
213
- <Input
215
+ <EmailInput
214
216
  id="email"
215
217
  name="email"
216
- type="email"
217
218
  required
218
219
  disabled={disabled}
219
- autoComplete="email"
220
220
  aria-invalid={Boolean(fieldErrors.email)}
221
221
  aria-describedby={fieldErrors.email ? 'email-error' : undefined}
222
222
  className={fieldErrors.email ? 'border-red-500 aria-invalid:ring-destructive' : undefined}
@@ -280,10 +280,9 @@ export default function OnboardingPageClient({ onboardingEnabled }: Props) {
280
280
  </div>
281
281
  <div className="grid gap-1">
282
282
  <Label htmlFor="password">{translate('onboarding.form.password', 'Password')}</Label>
283
- <Input
283
+ <PasswordInput
284
284
  id="password"
285
285
  name="password"
286
- type="password"
287
286
  required
288
287
  disabled={disabled}
289
288
  autoComplete="new-password"
@@ -301,10 +300,9 @@ export default function OnboardingPageClient({ onboardingEnabled }: Props) {
301
300
  </div>
302
301
  <div className="grid gap-1">
303
302
  <Label htmlFor="confirmPassword">{translate('onboarding.form.confirmPassword', 'Confirm password')}</Label>
304
- <Input
303
+ <PasswordInput
305
304
  id="confirmPassword"
306
305
  name="confirmPassword"
307
- type="password"
308
306
  required
309
307
  disabled={disabled}
310
308
  autoComplete="new-password"