 ec58a9dd70
			
		
	
	
		ec58a9dd70
		
			
		
	
	
	
	
		
			
			* dotenv refactoring * dotenv fixes * Env variables cleanup * Updates e2e variables * Moves environment file to types * Removes conflicting configs * Readds missing variables * Fixes * More fixes * Update .env.example * Update yarn.lock * Update turbo.json * Fixes e2e * Temp fix * disables cache for lint * Please work * I'm getting desperate here. * Matches node versions * Take 2 * Revert "Take 2" This reverts commit a735f47f2325c2040168e0cd99dea0fc357a791f. * Update .env.example
		
			
				
	
	
		
			210 lines
		
	
	
	
		
			8.1 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			210 lines
		
	
	
	
		
			8.1 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
| import { HashtagIcon, InformationCircleIcon, LinkIcon, PhotographIcon } from "@heroicons/react/solid";
 | |
| import React, { useRef, useState } from "react";
 | |
| 
 | |
| import showToast from "@calcom/lib/notification";
 | |
| import { Alert } from "@calcom/ui/Alert";
 | |
| import Button from "@calcom/ui/Button";
 | |
| import { TextField } from "@calcom/ui/form/fields";
 | |
| 
 | |
| import { useLocale } from "@lib/hooks/useLocale";
 | |
| import { TeamWithMembers } from "@lib/queries/teams";
 | |
| import { trpc } from "@lib/trpc";
 | |
| 
 | |
| import ImageUploader from "@components/ImageUploader";
 | |
| import SettingInputContainer from "@components/ui/SettingInputContainer";
 | |
| 
 | |
| interface Props {
 | |
|   team: TeamWithMembers | null | undefined;
 | |
| }
 | |
| 
 | |
| export default function TeamSettings(props: Props) {
 | |
|   const { t } = useLocale();
 | |
| 
 | |
|   const [hasErrors, setHasErrors] = useState(false);
 | |
|   const [errorMessage, setErrorMessage] = useState("");
 | |
| 
 | |
|   const team = props.team;
 | |
|   const hasLogo = !!team?.logo;
 | |
| 
 | |
|   const utils = trpc.useContext();
 | |
|   const mutation = trpc.useMutation("viewer.teams.update", {
 | |
|     onError: (err) => {
 | |
|       setHasErrors(true);
 | |
|       setErrorMessage(err.message);
 | |
|     },
 | |
|     async onSuccess() {
 | |
|       await utils.invalidateQueries(["viewer.teams.get"]);
 | |
|       showToast(t("your_team_updated_successfully"), "success");
 | |
|       setHasErrors(false);
 | |
|     },
 | |
|   });
 | |
| 
 | |
|   const nameRef = useRef<HTMLInputElement>() as React.MutableRefObject<HTMLInputElement>;
 | |
|   const teamUrlRef = useRef<HTMLInputElement>() as React.MutableRefObject<HTMLInputElement>;
 | |
|   const descriptionRef = useRef<HTMLTextAreaElement>() as React.MutableRefObject<HTMLTextAreaElement>;
 | |
|   const hideBrandingRef = useRef<HTMLInputElement>() as React.MutableRefObject<HTMLInputElement>;
 | |
|   const logoRef = useRef<HTMLInputElement>() as React.MutableRefObject<HTMLInputElement>;
 | |
| 
 | |
|   function updateTeamData() {
 | |
|     if (!team) return;
 | |
|     const variables = {
 | |
|       name: nameRef.current?.value,
 | |
|       slug: teamUrlRef.current?.value,
 | |
|       bio: descriptionRef.current?.value,
 | |
|       hideBranding: hideBrandingRef.current?.checked,
 | |
|     };
 | |
|     // remove unchanged variables
 | |
|     for (const key in variables) {
 | |
|       if (variables[key] === team?.[key]) delete variables[key];
 | |
|     }
 | |
|     mutation.mutate({ id: team.id, ...variables });
 | |
|   }
 | |
| 
 | |
|   function updateLogo(newLogo: string) {
 | |
|     if (!team) return;
 | |
|     logoRef.current.value = newLogo;
 | |
|     mutation.mutate({ id: team.id, logo: newLogo });
 | |
|   }
 | |
| 
 | |
|   const removeLogo = () => updateLogo("");
 | |
| 
 | |
|   return (
 | |
|     <div className="divide-y divide-gray-200 lg:col-span-9">
 | |
|       <div className="">
 | |
|         {hasErrors && <Alert severity="error" title={errorMessage} />}
 | |
|         <form
 | |
|           className="divide-y divide-gray-200 lg:col-span-9"
 | |
|           onSubmit={(e) => {
 | |
|             e.preventDefault();
 | |
|             updateTeamData();
 | |
|           }}>
 | |
|           <div className="py-6">
 | |
|             <div className="flex flex-col lg:flex-row">
 | |
|               <div className="flex-grow space-y-6">
 | |
|                 <SettingInputContainer
 | |
|                   Icon={LinkIcon}
 | |
|                   label="Team URL"
 | |
|                   htmlFor="team-url"
 | |
|                   Input={
 | |
|                     <TextField
 | |
|                       name="" // typescript requires name but we don't want component to render name label
 | |
|                       id="team-url"
 | |
|                       addOnLeading={
 | |
|                         <span className="inline-flex items-center rounded-l-sm border border-r-0 border-gray-300 bg-gray-50 px-3 text-sm text-gray-500">
 | |
|                           {process.env.NEXT_PUBLIC_WEBSITE_URL}/{"team/"}
 | |
|                         </span>
 | |
|                       }
 | |
|                       ref={teamUrlRef}
 | |
|                       defaultValue={team?.slug as string}
 | |
|                     />
 | |
|                   }
 | |
|                 />
 | |
|                 <SettingInputContainer
 | |
|                   Icon={HashtagIcon}
 | |
|                   label="Team Name"
 | |
|                   htmlFor="name"
 | |
|                   Input={
 | |
|                     <input
 | |
|                       ref={nameRef}
 | |
|                       type="text"
 | |
|                       name="name"
 | |
|                       id="name"
 | |
|                       placeholder={t("your_team_name")}
 | |
|                       required
 | |
|                       className="mt-1 block w-full rounded-sm border border-gray-300 px-3 py-2 shadow-sm focus:border-neutral-800 focus:outline-none focus:ring-neutral-800 sm:text-sm"
 | |
|                       defaultValue={team?.name as string}
 | |
|                     />
 | |
|                   }
 | |
|                 />
 | |
|                 <hr />
 | |
|                 <div>
 | |
|                   <SettingInputContainer
 | |
|                     Icon={InformationCircleIcon}
 | |
|                     label={t("about")}
 | |
|                     htmlFor="about"
 | |
|                     Input={
 | |
|                       <>
 | |
|                         <textarea
 | |
|                           ref={descriptionRef}
 | |
|                           id="about"
 | |
|                           name="about"
 | |
|                           rows={3}
 | |
|                           defaultValue={team?.bio as string}
 | |
|                           className="mt-1 block w-full rounded-sm border-gray-300 shadow-sm focus:border-neutral-800 focus:ring-neutral-800 sm:text-sm"></textarea>
 | |
|                         <p className="mt-2 text-sm text-gray-500">{t("team_description")}</p>
 | |
|                       </>
 | |
|                     }
 | |
|                   />
 | |
|                 </div>
 | |
|                 <div>
 | |
|                   <SettingInputContainer
 | |
|                     Icon={PhotographIcon}
 | |
|                     label={"Logo"}
 | |
|                     htmlFor="avatar"
 | |
|                     Input={
 | |
|                       <>
 | |
|                         <div className="mt-1 flex">
 | |
|                           <input
 | |
|                             ref={logoRef}
 | |
|                             type="hidden"
 | |
|                             name="avatar"
 | |
|                             id="avatar"
 | |
|                             placeholder="URL"
 | |
|                             className="mt-1 block w-full rounded-sm border border-gray-300 px-3 py-2 shadow-sm focus:border-neutral-800 focus:outline-none focus:ring-neutral-800 sm:text-sm"
 | |
|                             defaultValue={team?.logo ?? undefined}
 | |
|                           />
 | |
|                           <ImageUploader
 | |
|                             target="logo"
 | |
|                             id="logo-upload"
 | |
|                             buttonMsg={hasLogo ? t("edit_logo") : t("upload_a_logo")}
 | |
|                             handleAvatarChange={updateLogo}
 | |
|                             imageSrc={team?.logo ?? undefined}
 | |
|                           />
 | |
|                           {hasLogo && (
 | |
|                             <Button
 | |
|                               onClick={removeLogo}
 | |
|                               color="secondary"
 | |
|                               type="button"
 | |
|                               className="ml-1 py-1 text-xs">
 | |
|                               {t("remove_logo")}
 | |
|                             </Button>
 | |
|                           )}
 | |
|                         </div>
 | |
|                       </>
 | |
|                     }
 | |
|                   />
 | |
| 
 | |
|                   <hr className="mt-6" />
 | |
|                 </div>
 | |
| 
 | |
|                 <div className="relative flex items-start">
 | |
|                   <div className="flex h-5 items-center">
 | |
|                     <input
 | |
|                       id="hide-branding"
 | |
|                       name="hide-branding"
 | |
|                       type="checkbox"
 | |
|                       ref={hideBrandingRef}
 | |
|                       defaultChecked={team?.hideBranding}
 | |
|                       className="h-4 w-4 rounded-sm border-gray-300 text-neutral-900 focus:ring-neutral-500"
 | |
|                     />
 | |
|                   </div>
 | |
|                   <div className="text-sm ltr:ml-3 rtl:mr-3">
 | |
|                     <label htmlFor="hide-branding" className="font-medium text-gray-700">
 | |
|                       {t("disable_cal_branding")}
 | |
|                     </label>
 | |
|                     <p className="text-gray-500">{t("disable_cal_branding_description")}</p>
 | |
|                   </div>
 | |
|                 </div>
 | |
|               </div>
 | |
|             </div>
 | |
|           </div>
 | |
|           <div className="flex justify-end py-4">
 | |
|             <Button type="submit" color="primary">
 | |
|               {t("save")}
 | |
|             </Button>
 | |
|           </div>
 | |
|         </form>
 | |
|       </div>
 | |
|     </div>
 | |
|   );
 | |
| }
 |