Files
calendar/apps/web/modules/settings/security/impersonation-view.tsx
T
853f9bc436 perf: do not import from @calcom/ui barrel file (#20184)
* Icon and IconName

* Button and ButtonGroup

* UserAvatar

* AvatarGroup

* Avatar

* WizardLayout

* Dialogs

* EmptyScreen

* showToast and TextField

* Editor

* Skeleton

* Skeleton

* TopBanner and showToast

* Button again

* more

* perf: Remove app-store reference from @calcom/ui

* more

* Fixing types

* Icon

* Fixed casing

* dropdown

* more

* Select

* more

* Badge

* List

* more

* Divider

* more

* fix

* fix type check

* refactor

* fix

* fix

* fix

* fix

* fix

* fix

* fix

* fix type check

* fix

* fix

* fix

* fix

* more

* more

* more

* more

* add index file to components/command

* fix

* fix

* fix

* fix imports

* fix

* fix

* fix

* fix

* fix

* fix

* fix

* fix build errors

* fix build errors

* fix

---------

Co-authored-by: Keith Williams <keithwillcode@gmail.com>
2025-03-19 19:00:55 -03:00

80 lines
2.4 KiB
TypeScript

"use client";
import { useState } from "react";
import { useLocale } from "@calcom/lib/hooks/useLocale";
import { trpc } from "@calcom/trpc/react";
import type { RouterOutputs } from "@calcom/trpc/react";
import { SettingsToggle } from "@calcom/ui/components/form";
import { SkeletonText, SkeletonContainer } from "@calcom/ui/components/skeleton";
import { showToast } from "@calcom/ui/components/toast";
const SkeletonLoader = () => {
return (
<SkeletonContainer>
<div className="border-subtle space-y-6 border border-t-0 px-4 py-8 sm:px-6">
<SkeletonText className="h-8 w-full" />
</div>
</SkeletonContainer>
);
};
const ProfileImpersonationView = ({ user }: { user: RouterOutputs["viewer"]["me"]["get"] }) => {
const { t } = useLocale();
const utils = trpc.useUtils();
const [disableImpersonation, setDisableImpersonation] = useState<boolean | undefined>(
user?.disableImpersonation
);
const mutation = trpc.viewer.updateProfile.useMutation({
onSuccess: () => {
showToast(t("profile_updated_successfully"), "success");
},
onSettled: () => {
utils.viewer.me.invalidate();
},
onMutate: async ({ disableImpersonation }) => {
await utils.viewer.me.get.cancel();
const previousValue = utils.viewer.me.get.getData();
setDisableImpersonation(disableImpersonation);
return { previousValue };
},
onError: (error, variables, context) => {
if (context?.previousValue) {
utils.viewer.me.get.setData(undefined, context.previousValue);
setDisableImpersonation(context.previousValue?.disableImpersonation);
}
showToast(`${t("error")}, ${error.message}`, "error");
},
});
return (
<>
<div>
<SettingsToggle
toggleSwitchAtTheEnd={true}
title={t("user_impersonation_heading")}
description={t("user_impersonation_description")}
checked={!disableImpersonation}
onCheckedChange={(checked) => {
mutation.mutate({ disableImpersonation: !checked });
}}
switchContainerClassName="rounded-t-none border-t-0"
disabled={mutation.isPending}
/>
</div>
</>
);
};
const ProfileImpersonationViewWrapper = () => {
const { data: user, isPending } = trpc.viewer.me.get.useQuery();
if (isPending || !user) return <SkeletonLoader />;
return <ProfileImpersonationView user={user} />;
};
export default ProfileImpersonationViewWrapper;