Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 17 additions & 12 deletions src/features/auth/syncWordpress.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,20 +11,25 @@ export const syncWordpress = async (): Promise<void> => {
console.error('SyncWP: No ID token available');
return;
}
try {
const response = await fetch(
`${process.env.REACT_APP_CROWD_WP_URL}/wp-json/cognito-sync/v1/login`,
{
method: 'POST',
headers: { 'Content-Type': 'application/json' },
credentials: 'include',
body: JSON.stringify({ id_token: idToken }),
}
);

const response = await fetch(
`${process.env.REACT_APP_CROWD_WP_URL}/wp-json/cognito-sync/v1/login`,
{
method: 'POST',
headers: { 'Content-Type': 'application/json' },
credentials: 'include',
body: JSON.stringify({ id_token: idToken }),
}
);
const result = await response.json();

const result = await response.json();
if (isDev()) {
if (isDev()) {
// eslint-disable-next-line no-console
console.log('🚀 ~ syncWordpress ~ result:', result);
}
} catch (error: any) {
// eslint-disable-next-line no-console
console.log('🚀 ~ syncWordpress ~ result:', result);
console.error('SyncWP error:', error);
}
};
13 changes: 9 additions & 4 deletions src/pages/JoinPage/InvitedUserPage/SetPasswordForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import { ReactComponent as EyeHide } from '@zendeskgarden/svg-icons/src/16/eye-h
import { Field, FieldProps, Form, Formik, FormikHelpers } from 'formik';
import { useState } from 'react';
import { useTranslation } from 'react-i18next';
import { useNavigate } from 'react-router-dom';
import { useNavigate, useSearchParams } from 'react-router-dom';
import { appTheme } from 'src/app/theme';
import { PasswordRequirements } from 'src/common/components/PasswordRequirements';
import { useAuth } from 'src/features/auth/context';
Expand Down Expand Up @@ -48,6 +48,7 @@ export const SetPasswordForm = ({
const { t } = useTranslation();
const { signup, login, setNewPassword } = useAuth();
const navigate = useNavigate();
const [searchParams] = useSearchParams();
const sendGTMevent = useSendGTMevent({ loggedUser: false });
const [passwordInputType, setPasswordInputType] = useState('password');
const [confirmPasswordInputType, setConfirmPasswordInputType] =
Expand Down Expand Up @@ -98,7 +99,10 @@ export const SetPasswordForm = ({
// 3. L'utente è ora loggato, salva i dati dell'invito e vai all'onboarding
sessionStorage.setItem('inviteProfileId', profileId.toString());
sessionStorage.setItem('inviteToken', token);
navigate('/join/onboarding');

// Preserva i query params durante la navigazione
const queryString = searchParams.toString();
navigate(`/join/onboarding${queryString ? `?${queryString}` : ''}`);

return;
}
Expand All @@ -125,8 +129,9 @@ export const SetPasswordForm = ({
sessionStorage.setItem('inviteProfileId', profileId.toString());
sessionStorage.setItem('inviteToken', token);

// Redirect all'onboarding già loggato
navigate('/join/onboarding');
// Preserva i query params durante la navigazione
const queryString = searchParams.toString();
navigate(`/join/onboarding${queryString ? `?${queryString}` : ''}`);
} catch (loginError: any) {
// Se il login fallisce perché serve conferma email
if (loginError.message?.includes('User is not confirmed')) {
Expand Down
11 changes: 10 additions & 1 deletion src/pages/JoinPage/OnboardingPage/OnboardingProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,16 @@ export interface OnboardingUserData {
type: 'new' | 'invite';
}

export interface QueryParams {
template?: number;
[key: string]: string | number | undefined;
}

interface OnboardingContextType {
step: number;
data: OnboardingData;
userData: OnboardingUserData;
queryParams: QueryParams;
setStep: (step: number) => void;
updateData: (data: Partial<OnboardingData>) => void;
}
Expand All @@ -40,11 +46,13 @@ const OnboardingContext = createContext<OnboardingContextType | null>(null);

interface OnboardingProviderProps {
userData: OnboardingUserData;
queryParams?: QueryParams;
children: (context: OnboardingContextType) => ReactNode;
}

export const OnboardingProvider = ({
userData,
queryParams = {},
children,
}: OnboardingProviderProps) => {
const [step, setStep] = useState(1);
Expand Down Expand Up @@ -90,9 +98,10 @@ export const OnboardingProvider = ({
setStep,
data,
userData,
queryParams,
updateData,
}),
[step, data, userData]
[step, data, userData, queryParams]
);

return (
Expand Down
16 changes: 4 additions & 12 deletions src/pages/JoinPage/OnboardingPage/Steps/PersonalInfoStep.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import {
} from 'formik';
import { useCallback, useEffect, useMemo, useRef } from 'react';
import { useTranslation } from 'react-i18next';
import { useNavigate, useSearchParams } from 'react-router-dom';
import { useNavigate } from 'react-router-dom';
import { appTheme } from 'src/app/theme';
import {
useGetUsersRolesQuery,
Expand Down Expand Up @@ -116,9 +116,8 @@ const AutofillSync = () => {

export const PersonalInfoStep = () => {
const { t } = useTranslation();
const { data, userData, updateData, setStep } = useOnboarding();
const { data, userData, updateData, setStep, queryParams } = useOnboarding();
const navigate = useNavigate();
const [searchParams] = useSearchParams();
const sendGTMevent = useSendGTMevent({ loggedUser: false });
const [postUsers] = usePostUsersMutation();
const { data: dataRoles, isLoading: isLoadingRoles } =
Expand All @@ -128,15 +127,8 @@ export const PersonalInfoStep = () => {
const selectRef = useRef<HTMLDivElement>(null);
const roleSelectRef = useRef<HTMLDivElement>(null);

const templateParam = searchParams.get('template');
let templateId: number | undefined;

if (templateParam !== null) {
const parsed = Number(templateParam);
if (Number.isInteger(parsed)) {
templateId = parsed;
}
}
// Usa il templateId dai queryParams del provider
const templateId = queryParams.template;

const renderRolesOptions = useMemo(
() =>
Expand Down
37 changes: 18 additions & 19 deletions src/pages/JoinPage/OnboardingPage/Steps/WorkspaceStep.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,15 @@
} from '@appquality/unguess-design-system';
import { Field, FieldProps, Form, Formik, FormikHelpers } from 'formik';
import { useTranslation } from 'react-i18next';
import { useNavigate, useSearchParams } from 'react-router-dom';

import { appTheme } from 'src/app/theme';
import { usePostUsersMutation } from 'src/features/api';
import { useSendGTMevent } from 'src/hooks/useGTMevent';
import styled from 'styled-components';
import { AuthStepWrapper } from 'src/common/components/AuthCardWrapper';
import { useOnboarding } from '../OnboardingProvider';
import { getWorkspaceValidationSchema } from '../validationSchema';
import { sendToHubspot } from '../../sendToHubspot';

const FieldContainer = styled.div`
display: flex;
Expand All @@ -39,21 +40,11 @@

export const WorkspaceStep = () => {
const { t } = useTranslation();
const { data, userData, updateData, setStep } = useOnboarding();
const navigate = useNavigate();
const [searchParams] = useSearchParams();
const { data, userData, updateData, setStep, queryParams } = useOnboarding();
const sendGTMevent = useSendGTMevent({ loggedUser: false });
const [postUsers] = usePostUsersMutation();

const templateParam = searchParams.get('template');
let templateId: number | undefined;

if (templateParam !== null) {
const parsed = Number(templateParam);
if (Number.isInteger(parsed)) {
templateId = parsed;
}
}
const templateId = queryParams.template;
const redirectTo = queryParams.redirect as string | undefined;

const handleSubmit = async (
values: WorkspaceFormValues,
Expand Down Expand Up @@ -104,18 +95,26 @@
content: res.projectId ? 'with project' : 'without project',
});

try {
await sendToHubspot({
email: userData.email!,
firstName: data.name,
lastName: data.surname,
searchParams: queryParams,
});
} catch (err) {
console.error('Error sending data to HubSpot:', err);

Check warning on line 106 in src/pages/JoinPage/OnboardingPage/Steps/WorkspaceStep.tsx

View workflow job for this annotation

GitHub Actions / validate

Unexpected console statement
}

// Pulisci sessionStorage per utenti invitati
if (userData.type === 'invite') {
sessionStorage.removeItem('inviteProfileId');
sessionStorage.removeItem('inviteToken');
}

// Redirect appropriato (utente già loggato)
if (res.projectId) {
navigate(`/projects/${res.projectId}`);
} else {
navigate('/');
}
const redirectTarget = res.projectId ? `/projects/${res.projectId}` : '/';
window.location.href = redirectTo || redirectTarget;
} catch (error: any) {
// eslint-disable-next-line no-console
console.error('Onboarding save error:', error);
Expand Down
27 changes: 25 additions & 2 deletions src/pages/JoinPage/OnboardingPage/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
* Step 2: Nome workspace
*/
import { useTranslation } from 'react-i18next';
import { useSearchParams } from 'react-router-dom';
import { LayoutWrapper } from 'src/common/components/LayoutWrapper';
import { Track } from 'src/common/Track';
import { useGetUsersMeQuery } from 'src/features/api';
Expand All @@ -15,7 +16,11 @@
import { AuthHeader } from '../../LoginPage/parts/AuthHeader';
import { AuthFooter } from '../../LoginPage/parts/AuthFooter';
import { ImagesColumn } from '../ImagesColumn';
import { OnboardingProvider, OnboardingUserData } from './OnboardingProvider';
import {
OnboardingProvider,
OnboardingUserData,
QueryParams,
} from './OnboardingProvider';
import { PersonalInfoStep } from './Steps/PersonalInfoStep';
import { WorkspaceStep } from './Steps/WorkspaceStep';

Expand Down Expand Up @@ -80,6 +85,24 @@
const OnboardingPage = () => {
const { t } = useTranslation();
const { data: currentUser, isLoading } = useGetUsersMeQuery();
const [searchParams] = useSearchParams();

// Estrai i parametri query string
const queryParams: QueryParams = {};
const templateParam = searchParams.get('template');
if (templateParam !== null) {
const parsed = Number(templateParam);
if (Number.isInteger(parsed)) {
queryParams.template = parsed;
}
}

// Copia tutti gli altri parametri (utm_source, utm_medium, utm_campaign, etc.)
searchParams.forEach((value, key) => {
if (key !== 'template') {
queryParams[key] = value;

Check warning on line 103 in src/pages/JoinPage/OnboardingPage/index.tsx

View workflow job for this annotation

GitHub Actions / validate

Generic Object Injection Sink
}
});

// Costruisci userData da useGetUsersMeQuery
let userData: OnboardingUserData | undefined;
Expand Down Expand Up @@ -120,7 +143,7 @@
description={t('__PAGE_ONBOARDING_DESCRIPTION')}
metaTags={meta}
>
<OnboardingProvider userData={userData}>
<OnboardingProvider userData={userData} queryParams={queryParams}>
{({ step }) => (
<PageWrapper step={step + 1}>
<AuthHeader />
Expand Down
20 changes: 17 additions & 3 deletions src/pages/JoinPage/RouteGuards.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@
* RouteGuards - Componenti per proteggere le route di JoinPage
*/
import { ReactNode } from 'react';
import { Navigate } from 'react-router-dom';
import { Navigate, useSearchParams } from 'react-router-dom';
import { PageLoader } from 'src/common/components/PageLoader';
import { useGetUsersMeQuery } from 'src/features/api';

export const PublicRoute = ({ children }: { children: ReactNode }) => {
const { data: userData, isLoading } = useGetUsersMeQuery();
const [searchParams] = useSearchParams();

if (isLoading) {
return <PageLoader />;
Expand All @@ -17,7 +18,13 @@ export const PublicRoute = ({ children }: { children: ReactNode }) => {
if (userData) {
// Se onboarding è pending
if (userData.onboarding_pending) {
return <Navigate to="/join/onboarding" replace />;
const queryString = searchParams.toString();
return (
<Navigate
to={`/join/onboarding${queryString ? `?${queryString}` : ''}`}
replace
/>
);
}

// Se l'utente ha completato l'onboarding
Expand All @@ -33,14 +40,21 @@ export const PublicRoute = ({ children }: { children: ReactNode }) => {
*/
export const OnboardingRoute = ({ children }: { children: ReactNode }) => {
const { data: userData, isLoading, error } = useGetUsersMeQuery();
const [searchParams] = useSearchParams();

if (isLoading) {
return <PageLoader />;
}

// Se non c'è utente autenticato o c'è un errore (es. 401, 403)
if (!userData || error) {
return <Navigate to="/join/signup" replace />;
const queryString = searchParams.toString();
return (
<Navigate
to={`/join/signup${queryString ? `?${queryString}` : ''}`}
replace
/>
);
}

// Se onboarding NON è pending, redirect alla home
Expand Down
6 changes: 4 additions & 2 deletions src/pages/JoinPage/SignupPage/ConfirmEmailForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import {
} from '@appquality/unguess-design-system';
import { useCallback, useEffect, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { useNavigate } from 'react-router-dom';
import { useNavigate, useSearchParams } from 'react-router-dom';
import { appTheme } from 'src/app/theme';
import { useAuth } from 'src/features/auth/context';
import { useSendGTMevent } from 'src/hooks/useGTMevent';
Expand All @@ -31,6 +31,7 @@ export const ConfirmEmailForm = ({
const { t } = useTranslation();
const { confirmSignup, login, resendSignupCode } = useAuth();
const navigate = useNavigate();
const [searchParams] = useSearchParams();
const sendGTMevent = useSendGTMevent({ loggedUser: false });

const [code, setCode] = useState('');
Expand Down Expand Up @@ -70,7 +71,8 @@ export const ConfirmEmailForm = ({
action: 'auto-login completed',
});

navigate('/join/onboarding');
const queryString = searchParams.toString();
navigate(`/join/onboarding${queryString ? `?${queryString}` : ''}`);
} catch (err: any) {
// eslint-disable-next-line no-console
console.error('Confirmation error:', err);
Expand Down
13 changes: 6 additions & 7 deletions src/pages/JoinPage/sendToHubspot.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
email: string;
firstName: string;
lastName: string;
searchParams: Record<string, string | number | undefined>;
}) {
if (process.env.NODE_ENV === 'test') return false; // Skip actual API call during tests

Expand All @@ -21,14 +22,12 @@

const pageName = document.title;

const params = new URLSearchParams(window.location.search);

const utm = {
source: params.get('utm_source'),
medium: params.get('utm_medium'),
campaign: params.get('utm_campaign'),
term: params.get('utm_term'),
content: params.get('utm_content'),
source: data.searchParams.utm_source,
medium: data.searchParams.utm_medium,
campaign: data.searchParams.utm_campaign,
term: data.searchParams.utm_term,
content: data.searchParams.utm_content,
};

const payload = {
Expand Down Expand Up @@ -103,13 +102,13 @@
});

if (!response.ok) {
console.error(`HubSpot API error: ${response.statusText}`);

Check warning on line 105 in src/pages/JoinPage/sendToHubspot.ts

View workflow job for this annotation

GitHub Actions / validate

Unexpected console statement
return false;
}

return await response.json();
} catch (error) {
console.error('Error submitting to HubSpot:', error);

Check warning on line 111 in src/pages/JoinPage/sendToHubspot.ts

View workflow job for this annotation

GitHub Actions / validate

Unexpected console statement
return false;
}
}
Loading