diff --git a/apps/web/components/eventtype/EventTypeSingleLayout.tsx b/apps/web/components/eventtype/EventTypeSingleLayout.tsx
index 3218b90418..9523c34fb9 100644
--- a/apps/web/components/eventtype/EventTypeSingleLayout.tsx
+++ b/apps/web/components/eventtype/EventTypeSingleLayout.tsx
@@ -7,7 +7,7 @@ import { useMemo, useState, Suspense } from "react";
import type { UseFormReturn } from "react-hook-form";
import useLockedFieldsManager from "@calcom/features/ee/managed-event-types/hooks/useLockedFieldsManager";
-import { useOrgBrandingValues } from "@calcom/features/ee/organizations/hooks";
+import { useOrgBranding } from "@calcom/features/ee/organizations/context/provider";
import Shell from "@calcom/features/shell/Shell";
import { classNames } from "@calcom/lib";
import { CAL_URL } from "@calcom/lib/constants";
@@ -234,7 +234,7 @@ function EventTypeSingleLayout({
formMethods,
]);
- const orgBranding = useOrgBrandingValues();
+ const orgBranding = useOrgBranding();
const isOrgEvent = orgBranding?.fullDomain;
const permalink = `${orgBranding?.fullDomain ?? CAL_URL}/${
team ? `${!isOrgEvent ? "team/" : ""}${team.slug}` : eventType.users[0].username
diff --git a/apps/web/lib/app-providers.tsx b/apps/web/lib/app-providers.tsx
index ac9f70e9dc..d9d5683ff9 100644
--- a/apps/web/lib/app-providers.tsx
+++ b/apps/web/lib/app-providers.tsx
@@ -1,5 +1,6 @@
import { TooltipProvider } from "@radix-ui/react-tooltip";
import { SessionProvider } from "next-auth/react";
+import { useSession } from "next-auth/react";
import { EventCollectionProvider } from "next-collect/client";
import type { SSRConfig } from "next-i18next";
import { appWithTranslation } from "next-i18next";
@@ -10,7 +11,6 @@ import { useRouter } from "next/router";
import type { ComponentProps, PropsWithChildren, ReactNode } from "react";
import { OrgBrandingProvider } from "@calcom/features/ee/organizations/context/provider";
-import { useOrgBrandingValues } from "@calcom/features/ee/organizations/hooks";
import DynamicHelpscoutProvider from "@calcom/features/ee/support/lib/helpscout/providerDynamic";
import DynamicIntercomProvider from "@calcom/features/ee/support/lib/intercom/providerDynamic";
import { FeatureProvider } from "@calcom/features/flags/context/provider";
@@ -218,9 +218,26 @@ function FeatureFlagsProvider({ children }: { children: React.ReactNode }) {
return {children};
}
+function useOrgBrandingValues() {
+ const session = useSession();
+
+ const res = trpc.viewer.organizations.getBrand.useQuery(undefined, {
+ // Only fetch if we have a session to avoid flooding logs with errors
+ enabled: session.status === "authenticated",
+ });
+
+ if (res.status === "loading") {
+ return undefined;
+ }
+
+ if (res.status === "error") return null;
+
+ return res.data;
+}
+
function OrgBrandProvider({ children }: { children: React.ReactNode }) {
const orgBrand = useOrgBrandingValues();
- return {children};
+ return {children};
}
const AppProviders = (props: AppPropsWithChildren) => {
diff --git a/apps/web/pages/event-types/index.tsx b/apps/web/pages/event-types/index.tsx
index bbc06b878c..72e5e2c53e 100644
--- a/apps/web/pages/event-types/index.tsx
+++ b/apps/web/pages/event-types/index.tsx
@@ -7,7 +7,7 @@ import type { FC } from "react";
import { useEffect, useState, memo } from "react";
import { z } from "zod";
-import { useOrgBrandingValues } from "@calcom/features/ee/organizations/hooks";
+import { useOrgBranding } from "@calcom/features/ee/organizations/context/provider";
import useIntercom from "@calcom/features/ee/support/lib/intercom/useIntercom";
import { EventTypeDescriptionLazy as EventTypeDescription } from "@calcom/features/eventtypes/components";
import CreateEventTypeDialog from "@calcom/features/eventtypes/components/CreateEventTypeDialog";
@@ -102,7 +102,7 @@ const querySchema = z.object({
const MobileTeamsTab: FC = (props) => {
const { eventTypeGroups } = props;
- const orgBranding = useOrgBrandingValues();
+ const orgBranding = useOrgBranding();
const tabs = eventTypeGroups.map((item) => ({
name: item.profile.name ?? "",
href: item.teamId ? `/event-types?teamId=${item.teamId}` : "/event-types",
@@ -200,7 +200,7 @@ const MemoizedItem = memo(Item);
export const EventTypeList = ({ group, groupIndex, readOnly, types }: EventTypeListProps): JSX.Element => {
const { t } = useLocale();
const router = useRouter();
- const orgBranding = useOrgBrandingValues();
+ const orgBranding = useOrgBranding();
const [parent] = useAutoAnimate();
const [deleteDialogOpen, setDeleteDialogOpen] = useState(false);
const [deleteDialogTypeId, setDeleteDialogTypeId] = useState(0);
@@ -700,7 +700,7 @@ const EventTypeListHeading = ({
}: EventTypeListHeadingProps): JSX.Element => {
const { t } = useLocale();
const router = useRouter();
- const orgBranding = useOrgBrandingValues();
+ const orgBranding = useOrgBranding();
const publishTeamMutation = trpc.viewer.teams.publish.useMutation({
onSuccess(data) {
@@ -809,7 +809,7 @@ const Actions = () => {
const SetupProfileBanner = ({ closeAction }: { closeAction: () => void }) => {
const { t } = useLocale();
- const orgBranding = useOrgBrandingValues();
+ const orgBranding = useOrgBranding();
return (
{
const router = useRouter();
const filters = getTeamsFiltersFromQuery(router.query);
- const orgBranding = useOrgBrandingValues();
+ const orgBranding = useOrgBranding();
// TODO: Maybe useSuspenseQuery to focus on success case only? Remember that it would crash the page when there is an error in query. Also, it won't support skeleton
const res = trpc.viewer.eventTypes.getByViewer.useQuery(filters && { filters });
@@ -906,7 +906,7 @@ const EventTypesPage = () => {
const { query } = router;
const { data: user } = useMeQuery();
const [showProfileBanner, setShowProfileBanner] = useState(false);
- const orgBranding = useOrgBrandingValues();
+ const orgBranding = useOrgBranding();
function closeBanner() {
setShowProfileBanner(false);
diff --git a/packages/app-store/routing-forms/components/FormActions.tsx b/packages/app-store/routing-forms/components/FormActions.tsx
index f705995660..10fcc42238 100644
--- a/packages/app-store/routing-forms/components/FormActions.tsx
+++ b/packages/app-store/routing-forms/components/FormActions.tsx
@@ -7,7 +7,7 @@ import { Controller } from "react-hook-form";
import { v4 as uuidv4 } from "uuid";
import { z } from "zod";
-import { useOrgBrandingValues } from "@calcom/features/ee/organizations/hooks";
+import { useOrgBranding } from "@calcom/features/ee/organizations/context/provider";
import { classNames } from "@calcom/lib";
import { CAL_URL } from "@calcom/lib/constants";
import { useLocale } from "@calcom/lib/hooks/useLocale";
@@ -402,7 +402,7 @@ export const FormAction = forwardRef(function FormAction {
const { t } = useLocale();
- const orgBranding = useOrgBrandingValues();
+ const orgBranding = useOrgBranding();
const { data: query, pushItemToKey, removeItemByKeyAndValue, removeByKey } = useFilterQuery();
const [searchText, setSearchText] = useState("");
diff --git a/packages/features/ee/organizations/context/provider.ts b/packages/features/ee/organizations/context/provider.ts
index e32e001611..bd09a395c8 100644
--- a/packages/features/ee/organizations/context/provider.ts
+++ b/packages/features/ee/organizations/context/provider.ts
@@ -22,19 +22,19 @@ export type OrganizationBranding =
/**
* Allows you to access the flags from context
*/
-const OrganizationBrandingContext = createContext(null);
+const OrganizationBrandingContext = createContext<{ orgBrand: OrganizationBranding } | null>(null);
/**
* Accesses the branding for an organization from context.
- *
* You need to render a further up to be able to use
* this component.
+ *
+ * @returns `undefined` when data isn't available yet, `null` when there's an error, and the data(which can be `null`) when it's available
*/
export function useOrgBranding() {
const orgBrandingContext = useContext(OrganizationBrandingContext);
- if (orgBrandingContext === null)
- throw new Error("Error: useOrganizationBranding was used outside of OrgBrandingProvider.");
- return orgBrandingContext as OrganizationBranding;
+ if (!orgBrandingContext) throw new Error("Error: useOrgBranding was used outside of OrgBrandingProvider.");
+ return orgBrandingContext.orgBrand;
}
/**
@@ -60,7 +60,7 @@ export function useOrgBranding() {
* `YourOwnComponent` or further down.
*
*/
-export function OrgBrandingProvider(props: {
+export function OrgBrandingProvider(props: {
value: F;
children: React.ReactNode;
}) {
diff --git a/packages/features/ee/organizations/hooks/index.ts b/packages/features/ee/organizations/hooks/index.ts
deleted file mode 100644
index 6b3c264a33..0000000000
--- a/packages/features/ee/organizations/hooks/index.ts
+++ /dev/null
@@ -1,14 +0,0 @@
-import { useSession } from "next-auth/react";
-
-import { trpc } from "@calcom/trpc/react";
-
-export function useOrgBrandingValues() {
- const session = useSession();
- return trpc.viewer.organizations.getBrand.useQuery(undefined, {
- // Only fetch if we have a session to avoid flooding logs with errors
- enabled: session.status === "authenticated",
- // This is important because usage of useOrgBrandingValues is spread across the app and there isn't going to be anything new on fetching on every new mount of a component
- // We can just refetch the query only when org slug or logo changes which would be not frequent
- staleTime: Infinity,
- }).data;
-}
diff --git a/packages/features/ee/organizations/pages/settings/profile.tsx b/packages/features/ee/organizations/pages/settings/profile.tsx
index ca2d9fb43f..0a111aa9f5 100644
--- a/packages/features/ee/organizations/pages/settings/profile.tsx
+++ b/packages/features/ee/organizations/pages/settings/profile.tsx
@@ -7,7 +7,6 @@ import { Controller, useForm } from "react-hook-form";
import { z } from "zod";
import LicenseRequired from "@calcom/features/ee/common/components/LicenseRequired";
-import { useOrgBrandingValues } from "@calcom/features/ee/organizations/hooks";
import { subdomainSuffix } from "@calcom/features/ee/organizations/lib/orgDomains";
import { WEBAPP_URL } from "@calcom/lib/constants";
import { getPlaceholderAvatar } from "@calcom/lib/defaultAvatarImage";
@@ -30,6 +29,7 @@ import {
} from "@calcom/ui";
import { getLayout } from "../../../../settings/layouts/SettingsLayout";
+import { useOrgBranding } from "../../../organizations/context/provider";
const orgProfileFormSchema = z.object({
name: z.string(),
@@ -42,7 +42,7 @@ const OrgProfileView = () => {
const router = useRouter();
const utils = trpc.useContext();
const [firstRender, setFirstRender] = useState(true);
- const orgBranding = useOrgBrandingValues();
+ const orgBranding = useOrgBranding();
useLayoutEffect(() => {
document.body.focus();
diff --git a/packages/features/ee/teams/components/CreateANewTeamForm.tsx b/packages/features/ee/teams/components/CreateANewTeamForm.tsx
index abcb0ae483..2c32d8ead1 100644
--- a/packages/features/ee/teams/components/CreateANewTeamForm.tsx
+++ b/packages/features/ee/teams/components/CreateANewTeamForm.tsx
@@ -4,7 +4,6 @@ import { Controller, useForm } from "react-hook-form";
import { z } from "zod";
import { extractDomainFromWebsiteUrl } from "@calcom/ee/organizations/lib/utils";
-import { useOrgBrandingValues } from "@calcom/features/ee/organizations/hooks";
import { getSafeRedirectUrl } from "@calcom/lib/getSafeRedirectUrl";
import { useLocale } from "@calcom/lib/hooks/useLocale";
import slugify from "@calcom/lib/slugify";
@@ -13,6 +12,7 @@ import { trpc } from "@calcom/trpc/react";
import { Avatar, Button, Form, ImageUploader, TextField, Alert, Label } from "@calcom/ui";
import { ArrowRight, Plus } from "@calcom/ui/components/icon";
+import { useOrgBranding } from "../../organizations/context/provider";
import type { NewTeamFormValues } from "../lib/types";
const querySchema = z.object({
@@ -26,7 +26,7 @@ export const CreateANewTeamForm = () => {
const telemetry = useTelemetry();
const parsedQuery = querySchema.safeParse(router.query);
const [serverErrorMessage, setServerErrorMessage] = useState(null);
- const orgBranding = useOrgBrandingValues();
+ const orgBranding = useOrgBranding();
const returnToParam =
(parsedQuery.success ? getSafeRedirectUrl(parsedQuery.data.returnTo) : "/settings/teams") ||
diff --git a/packages/features/ee/teams/components/MemberListItem.tsx b/packages/features/ee/teams/components/MemberListItem.tsx
index 90394181de..726ba3ff1f 100644
--- a/packages/features/ee/teams/components/MemberListItem.tsx
+++ b/packages/features/ee/teams/components/MemberListItem.tsx
@@ -2,7 +2,6 @@ import classNames from "classnames";
import { signIn } from "next-auth/react";
import { useState } from "react";
-import { useOrgBrandingValues } from "@calcom/features/ee/organizations/hooks";
import { WEBAPP_URL } from "@calcom/lib/constants";
import { useLocale } from "@calcom/lib/hooks/useLocale";
import { MembershipRole } from "@calcom/prisma/enums";
@@ -30,6 +29,7 @@ import {
} from "@calcom/ui";
import { ExternalLink, MoreHorizontal, Edit2, Lock, UserX } from "@calcom/ui/components/icon";
+import { useOrgBranding } from "../../organizations/context/provider";
import MemberChangeRoleModal from "./MemberChangeRoleModal";
import TeamAvailabilityModal from "./TeamAvailabilityModal";
import TeamPill, { TeamRole } from "./TeamPill";
@@ -54,7 +54,7 @@ const checkIsOrg = (team: Props["team"]) => {
export default function MemberListItem(props: Props) {
const { t } = useLocale();
- const orgBranding = useOrgBrandingValues();
+ const orgBranding = useOrgBranding();
const utils = trpc.useContext();
const [showChangeMemberRoleModal, setShowChangeMemberRoleModal] = useState(false);
diff --git a/packages/features/ee/teams/components/TeamListItem.tsx b/packages/features/ee/teams/components/TeamListItem.tsx
index d23cfbc64f..e80da3a9f8 100644
--- a/packages/features/ee/teams/components/TeamListItem.tsx
+++ b/packages/features/ee/teams/components/TeamListItem.tsx
@@ -4,7 +4,6 @@ import { useState } from "react";
import InviteLinkSettingsModal from "@calcom/ee/teams/components/InviteLinkSettingsModal";
import MemberInvitationModal from "@calcom/ee/teams/components/MemberInvitationModal";
-import { useOrgBrandingValues } from "@calcom/features/ee/organizations/hooks";
import classNames from "@calcom/lib/classNames";
import { getPlaceholderAvatar } from "@calcom/lib/defaultAvatarImage";
import { useLocale } from "@calcom/lib/hooks/useLocale";
@@ -40,6 +39,7 @@ import {
X,
} from "@calcom/ui/components/icon";
+import { useOrgBranding } from "../../organizations/context/provider";
import { TeamRole } from "./TeamPill";
interface Props {
@@ -81,7 +81,7 @@ export default function TeamListItem(props: Props) {
const acceptInvite = () => acceptOrLeave(true);
const declineInvite = () => acceptOrLeave(false);
- const orgBranding = useOrgBrandingValues();
+ const orgBranding = useOrgBranding();
const isOwner = props.team.role === MembershipRole.OWNER;
const isInvitee = !props.team.accepted;
diff --git a/packages/features/ee/workflows/components/WorkflowListPage.tsx b/packages/features/ee/workflows/components/WorkflowListPage.tsx
index f1dd15334a..41e655b49b 100644
--- a/packages/features/ee/workflows/components/WorkflowListPage.tsx
+++ b/packages/features/ee/workflows/components/WorkflowListPage.tsx
@@ -22,7 +22,7 @@ import {
} from "@calcom/ui";
import { Edit2, Link as LinkIcon, MoreHorizontal, Trash2 } from "@calcom/ui/components/icon";
-import { useOrgBrandingValues } from "../../organizations/hooks";
+import { useOrgBranding } from "../../organizations/context/provider";
import { subdomainSuffix } from "../../organizations/lib/orgDomains";
import { getActionIcon } from "../lib/getActionIcon";
import { DeleteDialog } from "./DeleteDialog";
@@ -58,7 +58,7 @@ export default function WorkflowListPage({ workflows }: Props) {
const [workflowToDeleteId, setwWorkflowToDeleteId] = useState(0);
const router = useRouter();
- const orgBranding = useOrgBrandingValues();
+ const orgBranding = useOrgBranding();
const urlPrefix = orgBranding ? `${orgBranding.slug}.${subdomainSuffix()}` : CAL_URL;
return (
diff --git a/packages/features/eventtypes/components/CreateEventTypeDialog.tsx b/packages/features/eventtypes/components/CreateEventTypeDialog.tsx
index f61ed0b6e2..c4bf578973 100644
--- a/packages/features/eventtypes/components/CreateEventTypeDialog.tsx
+++ b/packages/features/eventtypes/components/CreateEventTypeDialog.tsx
@@ -6,7 +6,7 @@ import { useState } from "react";
import { useForm } from "react-hook-form";
import { z } from "zod";
-import { useOrgBrandingValues } from "@calcom/features/ee/organizations/hooks";
+import { useOrgBranding } from "@calcom/features/ee/organizations/context/provider";
import { useFlagMap } from "@calcom/features/flags/context/provider";
import { classNames } from "@calcom/lib";
import { useLocale } from "@calcom/lib/hooks/useLocale";
@@ -82,7 +82,7 @@ export default function CreateEventTypeDialog({
const { t } = useLocale();
const router = useRouter();
const [firstRender, setFirstRender] = useState(true);
- const orgBranding = useOrgBrandingValues();
+ const orgBranding = useOrgBranding();
const {
data: { teamId, eventPage: pageSlug },
diff --git a/packages/features/shell/Shell.tsx b/packages/features/shell/Shell.tsx
index f73f389024..e238aa830f 100644
--- a/packages/features/shell/Shell.tsx
+++ b/packages/features/shell/Shell.tsx
@@ -13,7 +13,6 @@ import { useIsEmbed } from "@calcom/embed-core/embed-iframe";
import UnconfirmedBookingBadge from "@calcom/features/bookings/UnconfirmedBookingBadge";
import ImpersonatingBanner from "@calcom/features/ee/impersonation/components/ImpersonatingBanner";
import { OrgUpgradeBanner } from "@calcom/features/ee/organizations/components/OrgUpgradeBanner";
-import { useOrgBrandingValues } from "@calcom/features/ee/organizations/hooks";
import HelpMenuItem from "@calcom/features/ee/support/components/HelpMenuItem";
import { TeamsUpgradeBanner } from "@calcom/features/ee/teams/components";
import { useFlagMap } from "@calcom/features/flags/context/provider";
@@ -79,6 +78,7 @@ import {
} from "@calcom/ui/components/icon";
import { Discord } from "@calcom/ui/components/icon/Discord";
+import { useOrgBranding } from "../ee/organizations/context/provider";
import FreshChatProvider from "../ee/support/lib/freshchat/FreshChatProvider";
import { NProgressNextRouter } from "./NProgressPageIndicator";
import { TeamInviteBadge } from "./TeamInviteBadge";
@@ -801,7 +801,8 @@ const getOrganizationUrl = (slug: string) =>
function SideBar({ bannersHeight, user }: SideBarProps) {
const { t, isLocaleReady } = useLocale();
- const orgBranding = useOrgBrandingValues();
+ const orgBranding = useOrgBranding();
+ const isOrgBrandingDataFetched = orgBranding !== undefined;
const publicPageUrl = useMemo(() => {
if (!user?.organizationId) return `${process.env.NEXT_PUBLIC_WEBSITE_URL}/${user?.username}`;
@@ -839,7 +840,7 @@ function SideBar({ bannersHeight, user }: SideBarProps) {
className="desktop-transparent bg-muted border-muted fixed left-0 hidden h-full max-h-screen w-14 flex-col overflow-y-auto overflow-x-hidden border-r dark:bg-gradient-to-tr dark:from-[#2a2a2a] dark:to-[#1c1c1c] md:sticky md:flex lg:w-56 lg:px-3">
- {orgBranding ? (
+ {!isOrgBrandingDataFetched ? null : orgBranding ? (
(null);
const [state, dispatch] = useReducer(reducer, initialState);
const { t } = useLocale();
- const orgBranding = useOrgBrandingValues();
+ const orgBranding = useOrgBranding();
const { data, isLoading, fetchNextPage, isFetching } =
trpc.viewer.organizations.listMembers.useInfiniteQuery(
diff --git a/packages/features/users/components/UserTable/UserTableActions.tsx b/packages/features/users/components/UserTable/UserTableActions.tsx
index d15148635b..c2cb24b4ad 100644
--- a/packages/features/users/components/UserTable/UserTableActions.tsx
+++ b/packages/features/users/components/UserTable/UserTableActions.tsx
@@ -14,7 +14,6 @@ import {
DropdownMenuSeparator,
} from "@calcom/ui";
-import { useOrgBrandingValues } from "../../../ee/organizations/hooks";
import type { Action } from "./UserListTable";
import type { User } from "./UserListTable";
@@ -34,7 +33,6 @@ export function TableActions({
};
}) {
const { t } = useLocale();
- const orgBranding = useOrgBrandingValues();
const usersProfileUrl = domain + "/" + user.username;
diff --git a/packages/lib/hooks/useBookerUrl.ts b/packages/lib/hooks/useBookerUrl.ts
index 37e0253cec..7b2eab67b7 100644
--- a/packages/lib/hooks/useBookerUrl.ts
+++ b/packages/lib/hooks/useBookerUrl.ts
@@ -1,7 +1,7 @@
-import { useOrgBrandingValues } from "@calcom/features/ee/organizations/hooks";
+import { useOrgBranding } from "@calcom/features/ee/organizations/context/provider";
import { WEBAPP_URL } from "@calcom/lib/constants";
export const useBookerUrl = () => {
- const orgBranding = useOrgBrandingValues();
+ const orgBranding = useOrgBranding();
return orgBranding?.fullDomain ?? WEBAPP_URL;
};