2
0

first commit

This commit is contained in:
2024-08-09 00:39:27 +02:00
commit 79688abe2e
5698 changed files with 497838 additions and 0 deletions

View File

@@ -0,0 +1,129 @@
import { useState } from "react";
import { Controller, useFormContext } from "react-hook-form";
import SectionBottomActions from "@calcom/features/settings/SectionBottomActions";
import { classNames } from "@calcom/lib";
import { DEFAULT_LIGHT_BRAND_COLOR, DEFAULT_DARK_BRAND_COLOR } from "@calcom/lib/constants";
import { checkWCAGContrastColor } from "@calcom/lib/getBrandColours";
import { useLocale } from "@calcom/lib/hooks/useLocale";
import { Button, ColorPicker, SettingsToggle, Alert } from "@calcom/ui";
type BrandColorsFormValues = {
brandColor: string;
darkBrandColor: string;
};
const BrandColorsForm = ({
onSubmit,
brandColor,
darkBrandColor,
}: {
onSubmit: (values: BrandColorsFormValues) => void;
brandColor: string | undefined;
darkBrandColor: string | undefined;
}) => {
const { t } = useLocale();
const brandColorsFormMethods = useFormContext();
const {
formState: { isSubmitting: isBrandColorsFormSubmitting, isDirty: isBrandColorsFormDirty },
} = brandColorsFormMethods;
const [isCustomBrandColorChecked, setIsCustomBrandColorChecked] = useState(
brandColor !== DEFAULT_LIGHT_BRAND_COLOR || darkBrandColor !== DEFAULT_DARK_BRAND_COLOR
);
const [darkModeError, setDarkModeError] = useState(false);
const [lightModeError, setLightModeError] = useState(false);
return (
<div className="mt-6">
<SettingsToggle
toggleSwitchAtTheEnd={true}
title={t("custom_brand_colors")}
description={t("customize_your_brand_colors")}
checked={isCustomBrandColorChecked}
onCheckedChange={(checked) => {
setIsCustomBrandColorChecked(checked);
if (!checked) {
onSubmit({
brandColor: DEFAULT_LIGHT_BRAND_COLOR,
darkBrandColor: DEFAULT_DARK_BRAND_COLOR,
});
}
}}
childrenClassName="lg:ml-0"
switchContainerClassName={classNames(
"py-6 px-4 sm:px-6 border-subtle rounded-xl border",
isCustomBrandColorChecked && "rounded-b-none"
)}>
<div className="border-subtle flex flex-col gap-6 border-x p-6">
<Controller
name="brandColor"
control={brandColorsFormMethods.control}
defaultValue={brandColor}
render={() => (
<div>
<p className="text-default mb-2 block text-sm font-medium">{t("light_brand_color")}</p>
<ColorPicker
defaultValue={brandColor || DEFAULT_LIGHT_BRAND_COLOR}
resetDefaultValue={DEFAULT_LIGHT_BRAND_COLOR}
onChange={(value) => {
try {
checkWCAGContrastColor("#ffffff", value);
setLightModeError(false);
brandColorsFormMethods.setValue("brandColor", value, { shouldDirty: true });
} catch (err) {
setLightModeError(false);
}
}}
/>
{lightModeError ? (
<div className="mt-4">
<Alert severity="warning" message={t("light_theme_contrast_error")} />
</div>
) : null}
</div>
)}
/>
<Controller
name="darkBrandColor"
control={brandColorsFormMethods.control}
defaultValue={darkBrandColor}
render={() => (
<div className="mt-6 sm:mt-0">
<p className="text-default mb-2 block text-sm font-medium">{t("dark_brand_color")}</p>
<ColorPicker
defaultValue={darkBrandColor || DEFAULT_DARK_BRAND_COLOR}
resetDefaultValue={DEFAULT_DARK_BRAND_COLOR}
onChange={(value) => {
try {
checkWCAGContrastColor("#101010", value);
setDarkModeError(false);
brandColorsFormMethods.setValue("darkBrandColor", value, { shouldDirty: true });
} catch (err) {
setDarkModeError(true);
}
}}
/>
{darkModeError ? (
<div className="mt-4">
<Alert severity="warning" message={t("dark_theme_contrast_error")} />
</div>
) : null}
</div>
)}
/>
</div>
<SectionBottomActions align="end">
<Button
disabled={isBrandColorsFormSubmitting || !isBrandColorsFormDirty}
color="primary"
type="submit">
{t("update")}
</Button>
</SectionBottomActions>
</SettingsToggle>
</div>
);
};
export default BrandColorsForm;

View File

@@ -0,0 +1,31 @@
import SectionBottomActions from "@calcom/features/settings/SectionBottomActions";
import { Meta, SkeletonButton, SkeletonContainer, SkeletonText } from "@calcom/ui";
export const AppearanceSkeletonLoader = ({ title, description }: { title: string; description: string }) => {
return (
<SkeletonContainer>
<Meta title={title} description={description} borderInShellHeader={false} />
<div className="border-subtle mt-6 flex items-center rounded-t-xl border p-6 text-sm">
<SkeletonText className="h-8 w-1/3" />
</div>
<div className="border-subtle space-y-6 border-x px-4 py-6 sm:px-6">
<div className="flex w-full items-center justify-center gap-6">
<div className="bg-emphasis h-32 flex-1 animate-pulse rounded-md p-5" />
<div className="bg-emphasis h-32 flex-1 animate-pulse rounded-md p-5" />
<div className="bg-emphasis h-32 flex-1 animate-pulse rounded-md p-5" />
</div>
<div className="flex justify-between">
<SkeletonText className="h-8 w-1/3" />
<SkeletonText className="h-8 w-1/3" />
</div>
<SkeletonText className="h-8 w-full" />
</div>
<div className="rounded-b-xl">
<SectionBottomActions align="end">
<SkeletonButton className="mr-6 h-8 w-20 rounded-md p-5" />
</SectionBottomActions>
</div>
</SkeletonContainer>
);
};

View File

@@ -0,0 +1,34 @@
import { useSession } from "next-auth/react";
import Link from "next/link";
import { useIsEmbed } from "@calcom/embed-core/embed-iframe";
import { APP_NAME, POWERED_BY_URL } from "@calcom/lib/constants";
import { useLocale } from "@calcom/lib/hooks/useLocale";
const PoweredByCal = ({ logoOnly }: { logoOnly?: boolean }) => {
const { t } = useLocale();
const session = useSession();
const isEmbed = useIsEmbed();
const hasValidLicense = session.data ? session.data.hasValidLicense : null;
return (
<div className={`p-2 text-center text-xs sm:text-right${isEmbed ? " max-w-3xl" : ""}`}>
<Link href={POWERED_BY_URL} target="_blank" className="text-subtle">
{!logoOnly && <>{t("powered_by")} </>}
{APP_NAME === "Cal.com" || !hasValidLicense ? (
<>
<img
className="relative -mt-px inline h-[10px] w-auto dark:invert"
src="/api/logo"
alt="Cal.com Logo"
/>
</>
) : (
<span className="text-emphasis font-semibold opacity-50 hover:opacity-100">{APP_NAME}</span>
)}
</Link>
</div>
);
};
export default PoweredByCal;