@open-mercato/onboarding 0.6.1-develop.3276.1.1fcd145078 → 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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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": ";
|
|
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.
|
|
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.
|
|
72
|
+
"@open-mercato/shared": "0.6.1-develop.3287.1.450f4ffb56"
|
|
73
73
|
},
|
|
74
74
|
"devDependencies": {
|
|
75
|
-
"@open-mercato/shared": "0.6.1-develop.
|
|
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
|
-
<
|
|
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
|
-
<
|
|
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
|
-
<
|
|
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"
|