Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
7ec6c15
feat: add responsive hidden column for smaller screens in PlanBody co…
marcbon Nov 18, 2025
2dcab9d
feat: implement responsive padding for Grid in PlanBody component
marcbon Nov 18, 2025
de47dc4
feat: add ScrollSpacer component for improved layout in ModulesList
marcbon Nov 18, 2025
334650e
feat: replace Col with HiddenColSm for responsive layout in PlanBody …
marcbon Nov 18, 2025
f4ed701
feat: hide BreadcrumbTabs on small screens for improved responsiveness
marcbon Nov 18, 2025
49d84a3
feat: enhance responsive layout in Header and TitleGroup components
marcbon Nov 18, 2025
6c3a78f
feat: add mobile responsiveness to Controls and PlanBody components
marcbon Nov 18, 2025
d050dc6
feat: add mobile navigation for ModulesList component
marcbon Nov 18, 2025
23ccf54
feat: enhance responsive layout in SummaryBody component for mobile d…
marcbon Nov 18, 2025
3bb7be1
feat: enhance mobile responsiveness in IntroductionCard component
marcbon Nov 18, 2025
26c0f0f
feat: add mobile alert for limited functionality in Plan page header
marcbon Nov 18, 2025
e1aaaa9
feat: hide remove/add buttons for mobile view in multiple components
marcbon Nov 18, 2025
8b3d645
feat: adjust styling for EmptyProjectContainer to improve layout cons…
marcbon Nov 20, 2025
b2679e1
feat: remove unused state and effect in ProjectEmptyState component
marcbon Nov 20, 2025
291307e
feat: close sidebar on mobile devices for improved navigation experience
marcbon Nov 20, 2025
1884b7b
chore: update @appquality/unguess-design-system to version 4.0.55--ca…
marcbon Nov 20, 2025
9e7be51
remove watchers from mobile
iacopolea Nov 21, 2025
a02ca50
feat: update viewport meta tag for improved mobile responsiveness
iacopolea Nov 21, 2025
c8a2a7a
fix: correct import order for useWindowSize in WatcherList component
iacopolea Nov 21, 2025
0503cfb
fix: hide column on mobile for improved layout in Gender component
iacopolea Nov 21, 2025
5fc29be
fix: adjust modal styling for improved appearance during quote requests
iacopolea Nov 21, 2025
8ca6772
fix: update condition to display modal based on quote request status
iacopolea Nov 21, 2025
c3b05c9
fix: update WaitModal styling to use padding instead of negative margin
iacopolea Nov 24, 2025
d5ba36b
fix: refactor tab navigation to use handleGoToTab for smoother scrolling
iacopolea Nov 25, 2025
6a3fbf3
feat: integrate analytics tracking for plan creation, confirmation, a…
iacopolea Nov 25, 2025
a0a3d0b
chore validate
iacopolea Nov 25, 2025
d393c94
fix: update condition to display tooltip based on mobile view and pla…
marcbon Nov 26, 2025
cd9c7a4
fix: remove inline overflow style from SendRequestModal body for impr…
marcbon Nov 26, 2025
11e6be1
fix: update unguess-design-system version to 4.0.55--canary.2ac110d.0
iacopolea Nov 26, 2025
aa8be3f
feat: replace analytics tracking with use-analytics integration acros…
iacopolea Nov 26, 2025
da11c8b
chore: update unguess-design-system version to 4.0.55
iacopolea Nov 26, 2025
cd64e90
Merge pull request #1478 from AppQuality/UN-2077-mobile
marcbon Nov 26, 2025
9f9ca0c
Merge pull request #1482 from AppQuality/UN-1976-tracking-plans
marcbon Nov 26, 2025
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
8 changes: 8 additions & 0 deletions .hintrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"extends": [
"development"
],
"hints": {
"meta-viewport": "off"
}
}
2 changes: 1 addition & 1 deletion index.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<head>
<meta charset="utf-8" />
<link rel="icon" href="%PUBLIC_URL%/static/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1" />
<meta name="theme-color" content="#003A57" />
<meta
name="description"
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"@analytics/google-tag-manager": "^0.6.0",
"@analytics/hubspot": "^0.5.1",
"@appquality/languages": "1.4.3",
"@appquality/unguess-design-system": "4.0.54",
"@appquality/unguess-design-system": "4.0.55",
"@atlaskit/pragmatic-drag-and-drop": "^1.7.4",
"@atlaskit/pragmatic-drag-and-drop-flourish": "^2.0.3",
"@atlaskit/pragmatic-drag-and-drop-hitbox": "^1.1.0",
Expand Down
10 changes: 10 additions & 0 deletions src/common/components/PlanCreationInterface/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import {
import { useActiveWorkspace } from 'src/hooks/useActiveWorkspace';
import { useLocalizeRoute } from 'src/hooks/useLocalizedRoute';
import styled from 'styled-components';
import { useAnalytics } from 'use-analytics';
import { v4 as uuidv4 } from 'uuid';
import { PlanCreationContextProvider, usePlanCreationContext } from './Context';
import { ProjectDropdown } from './ProjectDropdown';
Expand Down Expand Up @@ -84,6 +85,7 @@ const DrawerFooter = ({
const plansRoute = useLocalizeRoute('plans');
const { t } = useTranslation();
const { templateId } = useParams();
const { track } = useAnalytics();

const handleConfirm = async () => {
setFieldIsTouched(true);
Expand All @@ -99,6 +101,14 @@ const DrawerFooter = ({
.unwrap()
.then(({ id }) => {
const planRoute = `${plansRoute}${id}`;
track('planDraftCreated', {
planId: id.toString(),
templateId: selectedTemplate.id.toString(),
templateName: selectedTemplate.name,
planStatus: selectedTemplate,
standardPrice: selectedTemplate.price,
isTailored: selectedTemplate.isTailored,
});
navigate(planRoute);
})
.catch((error) => {
Expand Down
12 changes: 12 additions & 0 deletions src/features/navigation/Navigation/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@ import { Content } from '@appquality/unguess-design-system';
import { ComponentProps, useEffect, useMemo } from 'react';
import { useParams } from 'react-router-dom';
import { useAppDispatch } from 'src/app/hooks';
import { appTheme } from 'src/app/theme';
import { AppSidebar } from 'src/common/components/navigation/sidebar';
import {
setSidebarOpen,
toggleSidebar,
} from 'src/features/navigation/navigationSlice';
import { NoActiveWorkSpaceState } from 'src/features/templates/NoActiveWorkspaceState';
import { useActiveWorkspace } from 'src/hooks/useActiveWorkspace';
import useWindowSize from 'src/hooks/useWindowSize';
import { styled } from 'styled-components';
import { NavigationHeader } from './NavigationHeader';
import { NavigationProfileModal } from './NavigationProfileModal';
Expand Down Expand Up @@ -36,8 +38,18 @@ export const Navigation = ({
}) => {
const dispatch = useAppDispatch();
const { activeWorkspace, isLoading } = useActiveWorkspace();
const { width } = useWindowSize();
const breakpointSm = parseInt(appTheme.breakpoints.sm, 10);
const isMobile = width < breakpointSm;

useEffect(() => {
// Always closed sidebar state on mobile
if (isMobile) {
dispatch(setSidebarOpen(false));
return;
}

// Set sidebar state based on route
switch (route) {
case 'service':
case 'campaigns':
Expand Down
11 changes: 2 additions & 9 deletions src/locales/en/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -1233,15 +1233,6 @@
"__PROFILE_MODAL_GO_TO_PROFILE": "Edit profile",
"__PROFILE_MODAL_LANGUAGES_TITLE": "Change Language",
"__PROFILE_MODAL_LOGOUT_TITLE": "Log Out",
"__PROFILE_MODAL_NOTIFICATIONS_INTRO": "Manage the notifications we send you by email.",
"__PROFILE_MODAL_NOTIFICATIONS_OUTRO_P_1": " ",
"__PROFILE_MODAL_NOTIFICATIONS_OUTRO_P_2": "Enable to receive all updates: comments, mentions, quotes on the platform, confirmations, activity timelines, and invitations.",
"__PROFILE_MODAL_NOTIFICATIONS_OUTRO_P_3": "Disable to receive only essentials: mentions, quotes on the platform, activity confirmations, and invitations.",
"__PROFILE_MODAL_NOTIFICATIONS_TITLE": "Notifications settings",
"__PROFILE_MODAL_NOTIFICATIONS_TOGGLE_OFF": "No",
"__PROFILE_MODAL_NOTIFICATIONS_TOGGLE_ON": "Yes",
"__PROFILE_MODAL_NOTIFICATIONS_TOGGLE_TITLE": "Allow notifications",
"__PROFILE_MODAL_NOTIFICATIONS_UPDATED": "Changes saved",
"__PROFILE_MODAL_PRIVACY_ITEM_LABEL": "Privacy settings",
"__PROFILE_PAGE_COMPANY_SIZE_REQUIRED_ERROR": "Company size is required",
"__PROFILE_PAGE_CONFIRM_PASSWORD_MUST_MATCH_NEW_PASSWORD": "The confirmation password must match the new password",
Expand Down Expand Up @@ -1514,6 +1505,8 @@
"PLAN_GLOBAL_ALERT_APPROVED_STATE_TITLE": "The activity has been successfully launched!",
"PLAN_GLOBAL_ALERT_AWATING_STATE_MESSAGE": "Review details and confirm to launch.",
"PLAN_GLOBAL_ALERT_AWATING_STATE_TITLE": "Your quotation is ready!",
"PLAN_GLOBAL_ALERT_MOBILE_GO_TO_DESKTOP_MESSAGE": "For the best experience, please switch to a desktop device to access all features.",
"PLAN_GLOBAL_ALERT_MOBILE_GO_TO_DESKTOP_TITLE": "Limited functionality on mobile!",
"PLAN_GLOBAL_ALERT_PAYING_STATE_MESSAGE": "Your test will launch as scheduled",
"PLAN_GLOBAL_ALERT_PAYING_STATE_TITLE": "Payment in progress.",
"PLAN_GLOBAL_ALERT_PURCHASED_STATE_MESSAGE": "You will be notified when the first data is available on your dashboard",
Expand Down
11 changes: 2 additions & 9 deletions src/locales/it/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -1267,15 +1267,6 @@
"__PROFILE_MODAL_GO_TO_PROFILE": "",
"__PROFILE_MODAL_LANGUAGES_TITLE": "Cambia Lingua",
"__PROFILE_MODAL_LOGOUT_TITLE": "Esci",
"__PROFILE_MODAL_NOTIFICATIONS_INTRO": "Gestisci le notifiche che ti mandiamo per email.",
"__PROFILE_MODAL_NOTIFICATIONS_OUTRO_P_1": "",
"__PROFILE_MODAL_NOTIFICATIONS_OUTRO_P_2": "",
"__PROFILE_MODAL_NOTIFICATIONS_OUTRO_P_3": "",
"__PROFILE_MODAL_NOTIFICATIONS_TITLE": "Gestisci notifiche",
"__PROFILE_MODAL_NOTIFICATIONS_TOGGLE_OFF": "No",
"__PROFILE_MODAL_NOTIFICATIONS_TOGGLE_ON": "Si",
"__PROFILE_MODAL_NOTIFICATIONS_TOGGLE_TITLE": "Vuoi ricevere le notifiche?",
"__PROFILE_MODAL_NOTIFICATIONS_UPDATED": "Modifiche salvate",
"__PROFILE_MODAL_PRIVACY_ITEM_LABEL": "Opzioni Privacy",
"__PROFILE_PAGE_COMPANY_SIZE_REQUIRED_ERROR": "",
"__PROFILE_PAGE_CONFIRM_PASSWORD_MUST_MATCH_NEW_PASSWORD": "",
Expand Down Expand Up @@ -1557,6 +1548,8 @@
"PLAN_GLOBAL_ALERT_APPROVED_STATE_TITLE": "",
"PLAN_GLOBAL_ALERT_AWATING_STATE_MESSAGE": "",
"PLAN_GLOBAL_ALERT_AWATING_STATE_TITLE": "",
"PLAN_GLOBAL_ALERT_MOBILE_GO_TO_DESKTOP_MESSAGE": "",
"PLAN_GLOBAL_ALERT_MOBILE_GO_TO_DESKTOP_TITLE": "",
"PLAN_GLOBAL_ALERT_PAYING_STATE_MESSAGE": "",
"PLAN_GLOBAL_ALERT_PAYING_STATE_TITLE": "",
"PLAN_GLOBAL_ALERT_PURCHASED_STATE_MESSAGE": "",
Expand Down
25 changes: 3 additions & 22 deletions src/pages/Dashboard/empty-state/projectEmptyState.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {
XL,
XXL,
} from '@appquality/unguess-design-system';
import { useCallback, useEffect, useRef, useState } from 'react';
import { useCallback, useRef } from 'react';
import { Trans, useTranslation } from 'react-i18next';
import { appTheme } from 'src/app/theme';
import PlanCreationInterface from 'src/common/components/PlanCreationInterface';
Expand All @@ -26,8 +26,9 @@ const EmptyProjectContainer = styled.div`
align-items: center;
flex-direction: column;
width: 100%;
height: 100%;
position: relative;
padding: 0 ${appTheme.space.xxl};
padding: ${({ theme }) => `${theme.space.xxl}`};
`;

const ImageWrapper = styled.div`
Expand All @@ -39,7 +40,6 @@ const ImageWrapper = styled.div`
export const ProjectEmptyState = () => {
const { t } = useTranslation();
const containerRef = useRef<HTMLDivElement | null>(null);
const [distanceFromTop, setDistanceFromTop] = useState(0);
const canView = useCanAccessToActiveWorkspace();
const {
promoTemplates,
Expand All @@ -58,29 +58,10 @@ export const ProjectEmptyState = () => {
setIsDrawerOpen(true);
};

useEffect(() => {
const calculateDistance = () => {
if (containerRef.current) {
// Distance from the top of the page
const rect =
containerRef && containerRef?.current.getBoundingClientRect();
const scrollTop = window.scrollY || document.documentElement.scrollTop;
setDistanceFromTop(rect.top + scrollTop);
}
};

calculateDistance();
window.addEventListener('resize', calculateDistance);

return () => {
window.removeEventListener('resize', calculateDistance);
};
}, []);
return (
<EmptyProjectContainer
ref={containerRef}
style={{
height: `calc(100vh - ${distanceFromTop}px)`,
backgroundColor: canView ? '#f9feff' : 'transparent',
}}
>
Expand Down
2 changes: 1 addition & 1 deletion src/pages/JoinPage/WaitModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export const WaitModal = () => (
style={{
backgroundColor: 'transparent',
boxShadow: 'none',
marginTop: '-100px',
padding: '100px 20px',
}}
>
<Trans
Expand Down
10 changes: 10 additions & 0 deletions src/pages/Plan/Controls/ConfirmPlanButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { useState } from 'react';
import { useTranslation } from 'react-i18next';
import { useParams } from 'react-router-dom';
import { usePatchPlansByPidStatusMutation } from 'src/features/api';
import { useAnalytics } from 'use-analytics';
import { usePlan, usePlanIsPurchasable } from '../../../hooks/usePlan';
import { BuyButton } from '../summary/components/BuyButton';

Expand All @@ -14,6 +15,7 @@ const ConfirmPlanButton = () => {
const { plan, planComposedStatus } = usePlan(planId);
const { t } = useTranslation();
const isPurchasable = usePlanIsPurchasable(planId);
const { track } = useAnalytics();

if (!plan) return null;

Expand Down Expand Up @@ -43,6 +45,14 @@ const ConfirmPlanButton = () => {
.then(() => {
setIsSubmitted(false);
});
track('planActivityConfirmed', {
planId: planId?.toString(),
templateId: plan?.from_template?.id.toString(),
templateName: plan?.from_template?.title,
previousStatus: 'AwaitingApproval', // should be AwaitingApproval
newStatus: 'Accepted',
confirmedPrice: plan.price,
});
}}
>
{t('__PLAN_PAGE_SUMMARY_TAB_CONFIRMATION_CARD_CONFIRM_CTA')}
Expand Down
4 changes: 4 additions & 0 deletions src/pages/Plan/Controls/WatcherList/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import { ReactComponent as EyeIcon } from 'src/assets/icons/eye-icon.svg';
import { ReactComponent as InfoIcon } from 'src/assets/icons/info-icon.svg';
import { useGetPlansByPidWatchersQuery } from 'src/features/api';
import { usePlanIsApproved } from 'src/hooks/usePlan';
import useWindowSize from 'src/hooks/useWindowSize';
import { useIsWatching } from './hooks/useIsWatching';
import { MemberAddAutocomplete } from './MemberAddAutoComplete';
import { UserList } from './UserList';
Expand Down Expand Up @@ -49,13 +50,16 @@ const WatcherList = ({ planId }: { planId: string }) => {
useState<HTMLButtonElement | null>(null);
const appTheme = useTheme();
const isWatching = useIsWatching({ planId });
const { isMobile } = useWindowSize();
const { data: watchers, isLoading } = useGetPlansByPidWatchersQuery({
pid: planId,
});
const watchersCount = watchers ? watchers.items.length : 0;

const isApproved = usePlanIsApproved(planId);

if (isMobile) return null;

return (
<>
<Tooltip
Expand Down
7 changes: 6 additions & 1 deletion src/pages/Plan/Controls/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { useTranslation } from 'react-i18next';
import { useParams } from 'react-router-dom';
import { appTheme } from 'src/app/theme';
import { useModule } from 'src/features/modules/useModule';
import useWindowSize from 'src/hooks/useWindowSize';
import { useSubmit } from '../../../features/modules/useModuleConfiguration';
import { usePlan, usePlanIsPurchasable } from '../../../hooks/usePlan';
import { usePlanContext } from '../context/planContext';
Expand All @@ -20,6 +21,9 @@ import { WatcherList } from './WatcherList';

export const Controls = () => {
const { t } = useTranslation();
const { width } = useWindowSize();
const breakpointSm = parseInt(appTheme.breakpoints.sm, 10);
const isMobile = width < breakpointSm;
const [isRequestQuotationModalOpen, setRequestQuotationModalOpen] =
useState(false);
const {
Expand Down Expand Up @@ -86,7 +90,8 @@ export const Controls = () => {

{planComposedStatus !== 'AwaitingPayment' &&
planComposedStatus !== 'Paying' &&
planComposedStatus !== 'PurchasedPlan' && <IconButtonMenu />}
planComposedStatus !== 'PurchasedPlan' &&
!isMobile && <IconButtonMenu />}
{isDeleteModalOpen && planId && (
<DeletePlanModal
planId={planId}
Expand Down
23 changes: 17 additions & 6 deletions src/pages/Plan/ModulesList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { useEffect, useRef } from 'react';
import { useTranslation } from 'react-i18next';
import { useAppSelector } from 'src/app/hooks';
import { appTheme } from 'src/app/theme';
import useWindowSize from 'src/hooks/useWindowSize';
import styled from 'styled-components';
import { MODULE_GROUPS } from './common/constants';
import { GroupTitle } from './common/GroupTitle';
Expand All @@ -11,6 +12,14 @@ import { TabTitle } from './common/TabTitle';
import { usePlanContext } from './context/planContext';
import { getModuleBySlug, getModulesByTab } from './modules/Factory';

const ScrollSpacer = styled.div`
height: calc(100vh - 510px);

@media (max-width: ${({ theme }) => theme.breakpoints.sm}) {
display: none;
}
`;

const ModuleItem = styled.div<{
$isTasksOrTarget: boolean;
}>`
Expand Down Expand Up @@ -69,6 +78,10 @@ const GroupsWrapper = styled.div`
`;

export const ModulesList = () => {
const { width } = useWindowSize();
const breakpointSm = parseInt(appTheme.breakpoints.sm, 10);
const isMobile = width < breakpointSm;

const currentModules = useAppSelector(
(state) => state.planModules.currentModules
);
Expand Down Expand Up @@ -121,6 +134,9 @@ export const ModulesList = () => {
transition={{ duration: 0.15 }}
>
<TabTitle />
{isMobile && activeTab.name !== 'summary' && (
<ModulesBottomNavigation />
)}
<GroupsWrapper>
{groupConfig.map((group) => {
const groupModules = group.modules.filter((module) =>
Expand Down Expand Up @@ -152,12 +168,7 @@ export const ModulesList = () => {
})}
</GroupsWrapper>
{activeTab.name !== 'summary' && <ModulesBottomNavigation />}
<div
className="scroll-spacer"
style={{
height: `calc(100vh - 510px)`,
}}
/>
<ScrollSpacer className="scroll-spacer" />
</motion.div>
</AnimatePresence>
);
Expand Down
Loading
Loading