From 32f96392a3bb090d3bb6125b3ae835b59803de3f Mon Sep 17 00:00:00 2001 From: Dhruwang Date: Thu, 25 Dec 2025 16:36:16 +0530 Subject: [PATCH] refactor: introduce ContactsPageLayout component for improved structure - Replace PageContentWrapper and PageHeader with a new ContactsPageLayout component in Contacts, Attributes, and Segments pages. - Simplify the layout structure and enhance code readability. - Remove unused imports and comments in safe-identifier.ts. --- apps/web/lib/utils/safe-identifier.ts | 2 - .../modules/ee/contacts/attributes/page.tsx | 63 ++++------------- .../components/contacts-page-layout.tsx | 66 ++++++++++++++++++ apps/web/modules/ee/contacts/page.tsx | 66 ++++++------------ .../web/modules/ee/contacts/segments/page.tsx | 69 ++++++------------- 5 files changed, 122 insertions(+), 144 deletions(-) create mode 100644 apps/web/modules/ee/contacts/components/contacts-page-layout.tsx diff --git a/apps/web/lib/utils/safe-identifier.ts b/apps/web/lib/utils/safe-identifier.ts index 085c540dd8..c3feed1a1c 100644 --- a/apps/web/lib/utils/safe-identifier.ts +++ b/apps/web/lib/utils/safe-identifier.ts @@ -2,8 +2,6 @@ * Validates that a string is a safe identifier. * Safe identifiers can only contain lowercase letters, numbers, and underscores. * They cannot start with a number. - * - * This matches the validation used for survey variable names (see formbricks#5342). */ export const isSafeIdentifier = (value: string): boolean => { // Must start with a lowercase letter diff --git a/apps/web/modules/ee/contacts/attributes/page.tsx b/apps/web/modules/ee/contacts/attributes/page.tsx index 760bffdece..100e2457b2 100644 --- a/apps/web/modules/ee/contacts/attributes/page.tsx +++ b/apps/web/modules/ee/contacts/attributes/page.tsx @@ -1,13 +1,8 @@ -import { IS_FORMBRICKS_CLOUD } from "@/lib/constants"; import { getLocale } from "@/lingodotdev/language"; -import { getTranslate } from "@/lingodotdev/server"; -import { ContactsSecondaryNavigation } from "@/modules/ee/contacts/components/contacts-secondary-navigation"; +import { ContactsPageLayout } from "@/modules/ee/contacts/components/contacts-page-layout"; import { getContactAttributeKeys } from "@/modules/ee/contacts/lib/contact-attribute-keys"; import { getIsContactsEnabled } from "@/modules/ee/license-check/lib/utils"; import { getEnvironmentAuth } from "@/modules/environments/lib/utils"; -import { PageContentWrapper } from "@/modules/ui/components/page-content-wrapper"; -import { PageHeader } from "@/modules/ui/components/page-header"; -import { UpgradePrompt } from "@/modules/ui/components/upgrade-prompt"; import { AttributesTable } from "./components/attributes-table"; import { CreateAttributeModal } from "./components/create-attribute-modal"; @@ -17,7 +12,6 @@ export const AttributesPage = async ({ params: Promise<{ environmentId: string }>; }) => { const params = await paramsProps; - const t = await getTranslate(); const locale = await getLocale(); const [{ isReadOnly }, contactAttributeKeys] = await Promise.all([ @@ -28,46 +22,19 @@ export const AttributesPage = async ({ const isContactsEnabled = await getIsContactsEnabled(); return ( - - - ) : undefined - }> - - - - {isContactsEnabled ? ( - - ) : ( -
- -
- )} -
+ }> + + ); }; diff --git a/apps/web/modules/ee/contacts/components/contacts-page-layout.tsx b/apps/web/modules/ee/contacts/components/contacts-page-layout.tsx new file mode 100644 index 0000000000..78a67309cd --- /dev/null +++ b/apps/web/modules/ee/contacts/components/contacts-page-layout.tsx @@ -0,0 +1,66 @@ +import { ReactNode } from "react"; +import { IS_FORMBRICKS_CLOUD } from "@/lib/constants"; +import { getTranslate } from "@/lingodotdev/server"; +import { PageContentWrapper } from "@/modules/ui/components/page-content-wrapper"; +import { PageHeader } from "@/modules/ui/components/page-header"; +import { UpgradePrompt } from "@/modules/ui/components/upgrade-prompt"; +import { ContactsSecondaryNavigation } from "./contacts-secondary-navigation"; + +interface ContactsPageLayoutProps { + pageTitle: string; + activeId: string; + environmentId: string; + isContactsEnabled: boolean; + isReadOnly: boolean; + cta?: ReactNode; + children: ReactNode; + upgradePromptTitle?: string; + upgradePromptDescription?: string; +} + +export const ContactsPageLayout = async ({ + pageTitle, + activeId, + environmentId, + isContactsEnabled, + isReadOnly, + cta, + children, + upgradePromptTitle, + upgradePromptDescription, +}: ContactsPageLayoutProps) => { + const t = await getTranslate(); + + return ( + + + + + + {isContactsEnabled ? ( + children + ) : ( +
+ +
+ )} +
+ ); +}; diff --git a/apps/web/modules/ee/contacts/page.tsx b/apps/web/modules/ee/contacts/page.tsx index cb02ca8546..0a886acfd7 100644 --- a/apps/web/modules/ee/contacts/page.tsx +++ b/apps/web/modules/ee/contacts/page.tsx @@ -1,15 +1,12 @@ -import { IS_FORMBRICKS_CLOUD, ITEMS_PER_PAGE } from "@/lib/constants"; +import { ITEMS_PER_PAGE } from "@/lib/constants"; import { getTranslate } from "@/lingodotdev/server"; +import { ContactsPageLayout } from "@/modules/ee/contacts/components/contacts-page-layout"; import { UploadContactsCSVButton } from "@/modules/ee/contacts/components/upload-contacts-button"; import { getContactAttributeKeys } from "@/modules/ee/contacts/lib/contact-attribute-keys"; import { getContacts } from "@/modules/ee/contacts/lib/contacts"; import { getIsContactsEnabled, getIsQuotasEnabled } from "@/modules/ee/license-check/lib/utils"; import { getEnvironmentAuth } from "@/modules/environments/lib/utils"; -import { PageContentWrapper } from "@/modules/ui/components/page-content-wrapper"; -import { PageHeader } from "@/modules/ui/components/page-header"; -import { UpgradePrompt } from "@/modules/ui/components/upgrade-prompt"; import { ContactDataView } from "./components/contact-data-view"; -import { ContactsSecondaryNavigation } from "./components/contacts-secondary-navigation"; export const ContactsPage = async ({ params: paramsProps, @@ -34,46 +31,23 @@ export const ContactsPage = async ({ ); return ( - - - - - - {isContactsEnabled ? ( - = ITEMS_PER_PAGE} - isQuotasAllowed={isQuotasAllowed} - /> - ) : ( -
- -
- )} -
+ + = ITEMS_PER_PAGE} + isQuotasAllowed={isQuotasAllowed} + /> + ); }; diff --git a/apps/web/modules/ee/contacts/segments/page.tsx b/apps/web/modules/ee/contacts/segments/page.tsx index adb299eda8..0f9ba44c65 100644 --- a/apps/web/modules/ee/contacts/segments/page.tsx +++ b/apps/web/modules/ee/contacts/segments/page.tsx @@ -1,14 +1,10 @@ -import { IS_FORMBRICKS_CLOUD } from "@/lib/constants"; import { getTranslate } from "@/lingodotdev/server"; -import { ContactsSecondaryNavigation } from "@/modules/ee/contacts/components/contacts-secondary-navigation"; +import { ContactsPageLayout } from "@/modules/ee/contacts/components/contacts-page-layout"; import { getContactAttributeKeys } from "@/modules/ee/contacts/lib/contact-attribute-keys"; import { SegmentTable } from "@/modules/ee/contacts/segments/components/segment-table"; import { getSegments } from "@/modules/ee/contacts/segments/lib/segments"; import { getIsContactsEnabled } from "@/modules/ee/license-check/lib/utils"; import { getEnvironmentAuth } from "@/modules/environments/lib/utils"; -import { PageContentWrapper } from "@/modules/ui/components/page-content-wrapper"; -import { PageHeader } from "@/modules/ui/components/page-header"; -import { UpgradePrompt } from "@/modules/ui/components/upgrade-prompt"; import { CreateSegmentModal } from "./components/create-segment-modal"; export const SegmentsPage = async ({ @@ -35,50 +31,27 @@ export const SegmentsPage = async ({ const filteredSegments = segments.filter((segment) => !segment.isPrivate); return ( - - - ) : undefined - }> - - - - {isContactsEnabled ? ( - - ) : ( -
- -
- )} -
+ } + upgradePromptTitle={t("environments.segments.unlock_segments_title")} + upgradePromptDescription={t("environments.segments.unlock_segments_description")}> + + ); };