mirror of
https://github.com/fosrl/pangolin.git
synced 2025-11-28 12:15:24 +00:00
Compare commits
1 Commits
copilot/fi
...
1.12.2-s.4
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b5c6191c67 |
@@ -1421,6 +1421,9 @@
|
||||
"and": "and",
|
||||
"privacyPolicy": "privacy policy"
|
||||
},
|
||||
"signUpMarketing": {
|
||||
"keepMeInTheLoop": "Keep me in the loop with news, updates, and new features by email."
|
||||
},
|
||||
"siteRequired": "Site is required.",
|
||||
"olmTunnel": "Olm Tunnel",
|
||||
"olmTunnelDescription": "Use Olm for client connectivity",
|
||||
|
||||
@@ -16,7 +16,7 @@ import privateConfig from "#private/lib/config";
|
||||
import logger from "@server/logger";
|
||||
|
||||
export enum AudienceIds {
|
||||
SignUps = "5cfbf99b-c592-40a9-9b8a-577a4681c158",
|
||||
SignUps = "6c4e77b2-0851-4bd6-bac8-f51f91360f1a",
|
||||
Subscribed = "870b43fd-387f-44de-8fc1-707335f30b20",
|
||||
Churned = "f3ae92bd-2fdb-4d77-8746-2118afd62549",
|
||||
Newsletter = "5500c431-191c-42f0-a5d4-8b6d445b4ea0"
|
||||
|
||||
@@ -30,7 +30,8 @@ export const signupBodySchema = z.object({
|
||||
password: passwordSchema,
|
||||
inviteToken: z.string().optional(),
|
||||
inviteId: z.string().optional(),
|
||||
termsAcceptedTimestamp: z.string().nullable().optional()
|
||||
termsAcceptedTimestamp: z.string().nullable().optional(),
|
||||
marketingEmailConsent: z.boolean().optional()
|
||||
});
|
||||
|
||||
export type SignUpBody = z.infer<typeof signupBodySchema>;
|
||||
@@ -55,7 +56,7 @@ export async function signup(
|
||||
);
|
||||
}
|
||||
|
||||
const { email, password, inviteToken, inviteId, termsAcceptedTimestamp } =
|
||||
const { email, password, inviteToken, inviteId, termsAcceptedTimestamp, marketingEmailConsent } =
|
||||
parsedBody.data;
|
||||
|
||||
const passwordHash = await hashPassword(password);
|
||||
@@ -220,8 +221,8 @@ export async function signup(
|
||||
new Date(sess.expiresAt)
|
||||
);
|
||||
res.appendHeader("Set-Cookie", cookie);
|
||||
|
||||
if (build == "saas") {
|
||||
if (build == "saas" && marketingEmailConsent) {
|
||||
logger.debug(`User ${email} opted in to marketing emails during signup.`);
|
||||
moveEmailToAudience(email, AudienceIds.SignUps);
|
||||
}
|
||||
|
||||
|
||||
@@ -92,7 +92,8 @@ const formSchema = z
|
||||
message:
|
||||
"You must agree to the terms of service and privacy policy"
|
||||
}
|
||||
)
|
||||
),
|
||||
marketingEmailConsent: z.boolean().optional()
|
||||
})
|
||||
.refine((data) => data.password === data.confirmPassword, {
|
||||
path: ["confirmPassword"],
|
||||
@@ -123,7 +124,8 @@ export default function SignupForm({
|
||||
email: emailParam || "",
|
||||
password: "",
|
||||
confirmPassword: "",
|
||||
agreeToTerms: false
|
||||
agreeToTerms: false,
|
||||
marketingEmailConsent: false
|
||||
},
|
||||
mode: "onChange" // Enable real-time validation
|
||||
});
|
||||
@@ -135,7 +137,7 @@ export default function SignupForm({
|
||||
passwordValue === confirmPasswordValue;
|
||||
|
||||
async function onSubmit(values: z.infer<typeof formSchema>) {
|
||||
const { email, password } = values;
|
||||
const { email, password, marketingEmailConsent } = values;
|
||||
|
||||
setLoading(true);
|
||||
const res = await api
|
||||
@@ -144,7 +146,8 @@ export default function SignupForm({
|
||||
password,
|
||||
inviteId,
|
||||
inviteToken,
|
||||
termsAcceptedTimestamp: termsAgreedAt
|
||||
termsAcceptedTimestamp: termsAgreedAt,
|
||||
marketingEmailConsent: build === "saas" ? marketingEmailConsent : undefined
|
||||
})
|
||||
.catch((e) => {
|
||||
console.error(e);
|
||||
@@ -489,56 +492,78 @@ export default function SignupForm({
|
||||
)}
|
||||
/>
|
||||
{build === "saas" && (
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="agreeToTerms"
|
||||
render={({ field }) => (
|
||||
<FormItem className="flex flex-row items-center">
|
||||
<FormControl>
|
||||
<Checkbox
|
||||
checked={field.value}
|
||||
onCheckedChange={(checked) => {
|
||||
field.onChange(checked);
|
||||
handleTermsChange(
|
||||
checked as boolean
|
||||
);
|
||||
}}
|
||||
/>
|
||||
</FormControl>
|
||||
<div className="leading-none">
|
||||
<FormLabel className="text-sm font-normal">
|
||||
<div>
|
||||
{t(
|
||||
"signUpTerms.IAgreeToThe"
|
||||
)}{" "}
|
||||
<a
|
||||
href="https://pangolin.net/terms-of-service.html"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="text-primary hover:underline"
|
||||
>
|
||||
<>
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="agreeToTerms"
|
||||
render={({ field }) => (
|
||||
<FormItem className="flex flex-row items-center">
|
||||
<FormControl>
|
||||
<Checkbox
|
||||
checked={field.value}
|
||||
onCheckedChange={(checked) => {
|
||||
field.onChange(checked);
|
||||
handleTermsChange(
|
||||
checked as boolean
|
||||
);
|
||||
}}
|
||||
/>
|
||||
</FormControl>
|
||||
<div className="leading-none">
|
||||
<FormLabel className="text-sm font-normal">
|
||||
<div>
|
||||
{t(
|
||||
"signUpTerms.termsOfService"
|
||||
"signUpTerms.IAgreeToThe"
|
||||
)}{" "}
|
||||
</a>
|
||||
{t("signUpTerms.and")}{" "}
|
||||
<a
|
||||
href="https://pangolin.net/privacy-policy.html"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="text-primary hover:underline"
|
||||
>
|
||||
{t(
|
||||
"signUpTerms.privacyPolicy"
|
||||
)}
|
||||
</a>
|
||||
</div>
|
||||
</FormLabel>
|
||||
<FormMessage />
|
||||
</div>
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
<a
|
||||
href="https://pangolin.net/terms-of-service.html"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="text-primary hover:underline"
|
||||
>
|
||||
{t(
|
||||
"signUpTerms.termsOfService"
|
||||
)}{" "}
|
||||
</a>
|
||||
{t("signUpTerms.and")}{" "}
|
||||
<a
|
||||
href="https://pangolin.net/privacy-policy.html"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="text-primary hover:underline"
|
||||
>
|
||||
{t(
|
||||
"signUpTerms.privacyPolicy"
|
||||
)}
|
||||
</a>
|
||||
</div>
|
||||
</FormLabel>
|
||||
<FormMessage />
|
||||
</div>
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="marketingEmailConsent"
|
||||
render={({ field }) => (
|
||||
<FormItem className="flex flex-row items-start">
|
||||
<FormControl>
|
||||
<Checkbox
|
||||
checked={field.value}
|
||||
onCheckedChange={field.onChange}
|
||||
/>
|
||||
</FormControl>
|
||||
<div className="leading-none">
|
||||
<FormLabel className="text-sm font-normal">
|
||||
{t("signUpMarketing.keepMeInTheLoop")}
|
||||
</FormLabel>
|
||||
<FormMessage />
|
||||
</div>
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
|
||||
{error && (
|
||||
|
||||
Reference in New Issue
Block a user