Refactor: use EditableHeading in event-types/[type].tsx (#3468)
Co-authored-by: Peer Richelsen <peeroke@gmail.com>
This commit is contained in:
co-authored by
Peer Richelsen
parent
982ca3a783
commit
342efaed31
@@ -1,56 +0,0 @@
|
||||
// This component is abstracted from /event-types/[type] for common usecase.
|
||||
import { PencilIcon } from "@heroicons/react/solid";
|
||||
import { useState } from "react";
|
||||
|
||||
export default function PencilEdit({
|
||||
value,
|
||||
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
||||
onChange = () => {},
|
||||
placeholder = "",
|
||||
readOnly = false,
|
||||
}: {
|
||||
value: string;
|
||||
onChange?: (value: string) => void;
|
||||
placeholder?: string;
|
||||
readOnly?: boolean;
|
||||
}) {
|
||||
const [editIcon, setEditIcon] = useState(true);
|
||||
const onDivClick = !readOnly
|
||||
? () => {
|
||||
return setEditIcon(false);
|
||||
}
|
||||
: // eslint-disable-next-line @typescript-eslint/no-empty-function
|
||||
() => {};
|
||||
return (
|
||||
<div className="group relative min-h-[28px] cursor-pointer" onClick={onDivClick}>
|
||||
{editIcon ? (
|
||||
<>
|
||||
<h1
|
||||
style={{ fontSize: 22, letterSpacing: "-0.0009em" }}
|
||||
className="inline-block pl-0 text-gray-900 focus:text-black group-hover:text-gray-500">
|
||||
{value}
|
||||
</h1>
|
||||
{!readOnly ? (
|
||||
<PencilIcon className="ml-1 -mt-1 inline h-4 w-4 text-gray-700 group-hover:text-gray-500" />
|
||||
) : null}
|
||||
</>
|
||||
) : (
|
||||
<div style={{ marginBottom: -11 }}>
|
||||
<input
|
||||
type="text"
|
||||
autoFocus
|
||||
style={{ top: -6, fontSize: 22 }}
|
||||
required
|
||||
className="relative h-10 w-full cursor-pointer border-none bg-transparent pl-0 text-gray-900 hover:text-gray-700 focus:text-black focus:outline-none focus:ring-0"
|
||||
placeholder={placeholder}
|
||||
defaultValue={value}
|
||||
onBlur={(e) => {
|
||||
setEditIcon(true);
|
||||
onChange(e.target.value);
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -1,18 +1,31 @@
|
||||
import { PencilIcon } from "@heroicons/react/solid";
|
||||
import { useState } from "react";
|
||||
|
||||
const EditableHeading = ({ title, onChange }: { title: string; onChange: (value: string) => void }) => {
|
||||
const [editIcon, setEditIcon] = useState(true);
|
||||
const EditableHeading = ({
|
||||
title,
|
||||
onChange,
|
||||
placeholder = "",
|
||||
readOnly = false,
|
||||
}: {
|
||||
title: string;
|
||||
onChange?: (value: string) => void;
|
||||
placeholder?: string;
|
||||
readOnly?: boolean;
|
||||
}) => {
|
||||
const [isEditing, setIsEditing] = useState(false);
|
||||
const enableEditing = () => !readOnly && setIsEditing(true);
|
||||
return (
|
||||
<div className="group relative cursor-pointer" onClick={() => setEditIcon(false)}>
|
||||
{editIcon ? (
|
||||
<div className="group relative cursor-pointer" onClick={enableEditing}>
|
||||
{!isEditing ? (
|
||||
<>
|
||||
<h1
|
||||
style={{ fontSize: 22, letterSpacing: "-0.0009em" }}
|
||||
className="inline pl-0 text-gray-900 focus:text-black group-hover:text-gray-500">
|
||||
className="inline pl-0 normal-case text-gray-900 focus:text-black group-hover:text-gray-500">
|
||||
{title}
|
||||
</h1>
|
||||
<PencilIcon className="ml-1 -mt-1 inline h-4 w-4 text-gray-700 group-hover:text-gray-500" />
|
||||
{!readOnly ? (
|
||||
<PencilIcon className="ml-1 -mt-1 inline h-4 w-4 text-gray-700 group-hover:text-gray-500" />
|
||||
) : null}
|
||||
</>
|
||||
) : (
|
||||
<div style={{ marginBottom: -11 }}>
|
||||
@@ -22,8 +35,12 @@ const EditableHeading = ({ title, onChange }: { title: string; onChange: (value:
|
||||
style={{ top: -6, fontSize: 22 }}
|
||||
required
|
||||
className="relative h-10 w-full cursor-pointer border-none bg-transparent pl-0 text-gray-900 hover:text-gray-700 focus:text-black focus:outline-none focus:ring-0"
|
||||
placeholder={placeholder}
|
||||
defaultValue={title}
|
||||
onChange={(e) => onChange(e.target.value)}
|
||||
onBlur={(e) => {
|
||||
setIsEditing(false);
|
||||
onChange && onChange(e.target.value);
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -141,7 +141,7 @@ export default function Availability() {
|
||||
success={({ data }) => {
|
||||
return (
|
||||
<Shell
|
||||
heading={<EditableHeading title={data.schedule.name} onChange={setName} />}
|
||||
heading={<EditableHeading title={name || data.schedule.name} onChange={setName} />}
|
||||
subtitle={data.schedule.availability.map((availability) => (
|
||||
<span key={availability.id}>
|
||||
{availabilityAsString(availability, i18n.language)}
|
||||
|
||||
@@ -67,6 +67,7 @@ import { EditLocationDialog } from "@components/dialog/EditLocationDialog";
|
||||
import RecurringEventController from "@components/eventtype/RecurringEventController";
|
||||
import CustomInputTypeForm from "@components/pages/eventtypes/CustomInputTypeForm";
|
||||
import Badge from "@components/ui/Badge";
|
||||
import EditableHeading from "@components/ui/EditableHeading";
|
||||
import InfoBadge from "@components/ui/InfoBadge";
|
||||
import CheckboxField from "@components/ui/form/CheckboxField";
|
||||
import CheckedSelect from "@components/ui/form/CheckedSelect";
|
||||
@@ -310,7 +311,6 @@ const EventTypePage = (props: inferSSRProps<typeof getServerSideProps>) => {
|
||||
});
|
||||
const connectedCalendarsQuery = trpc.useQuery(["viewer.connectedCalendars"]);
|
||||
|
||||
const [editIcon, setEditIcon] = useState(true);
|
||||
const [showLocationModal, setShowLocationModal] = useState(false);
|
||||
const [selectedLocation, setSelectedLocation] = useState<OptionTypeBase | undefined>(undefined);
|
||||
const [selectedCustomInput, setSelectedCustomInput] = useState<EventTypeCustomInput | undefined>(undefined);
|
||||
@@ -318,7 +318,6 @@ const EventTypePage = (props: inferSSRProps<typeof getServerSideProps>) => {
|
||||
const [customInputs, setCustomInputs] = useState<EventTypeCustomInput[]>(
|
||||
eventType.customInputs.sort((a, b) => a.id - b.id) || []
|
||||
);
|
||||
const [tokensList, setTokensList] = useState<Array<Token>>([]);
|
||||
|
||||
const defaultSeatsPro = 6;
|
||||
const minSeats = 2;
|
||||
@@ -439,6 +438,7 @@ const EventTypePage = (props: inferSSRProps<typeof getServerSideProps>) => {
|
||||
|
||||
const formMethods = useForm<FormValues>({
|
||||
defaultValues: {
|
||||
title: eventType.title,
|
||||
locations: eventType.locations || [],
|
||||
recurringEvent: eventType.recurringEvent || null,
|
||||
schedule: eventType.schedule?.id,
|
||||
@@ -846,37 +846,10 @@ const EventTypePage = (props: inferSSRProps<typeof getServerSideProps>) => {
|
||||
<Shell
|
||||
title={t("event_type_title", { eventTypeTitle: eventType.title })}
|
||||
heading={
|
||||
<div className="group relative cursor-pointer" onClick={() => setEditIcon(false)}>
|
||||
{editIcon ? (
|
||||
<>
|
||||
<h1
|
||||
style={{ fontSize: 22, letterSpacing: "-0.0009em" }}
|
||||
className="inline pl-0 text-gray-900 focus:text-black group-hover:text-gray-500">
|
||||
{formMethods.getValues("title") && formMethods.getValues("title") !== ""
|
||||
? formMethods.getValues("title")
|
||||
: eventType.title}
|
||||
</h1>
|
||||
<PencilIcon className="ml-1 -mt-1 inline h-4 w-4 text-gray-700 group-hover:text-gray-500" />
|
||||
</>
|
||||
) : (
|
||||
<div style={{ marginBottom: -11 }}>
|
||||
<input
|
||||
type="text"
|
||||
autoFocus
|
||||
style={{ top: -6, fontSize: 22 }}
|
||||
required
|
||||
className="relative h-10 w-full cursor-pointer border-none bg-transparent pl-0 text-gray-900 hover:text-gray-700 focus:text-black focus:outline-none focus:ring-0"
|
||||
placeholder={t("quick_chat")}
|
||||
{...formMethods.register("title")}
|
||||
defaultValue={eventType.title}
|
||||
onBlur={() => {
|
||||
setEditIcon(true);
|
||||
formMethods.getValues("title") === "" && formMethods.setValue("title", eventType.title);
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<EditableHeading
|
||||
title={formMethods.watch("title")}
|
||||
onChange={(value) => formMethods.setValue("title", value)}
|
||||
/>
|
||||
}
|
||||
subtitle={eventType.description || ""}>
|
||||
<ClientSuspense fallback={<Loader />}>
|
||||
|
||||
@@ -14,7 +14,7 @@ import { Form, TextArea } from "@calcom/ui/form/fields";
|
||||
|
||||
import { inferSSRProps } from "@lib/types/inferSSRProps";
|
||||
|
||||
import PencilEdit from "@components/PencilEdit";
|
||||
import EditableHeading from "@components/ui/EditableHeading";
|
||||
|
||||
import RoutingShell from "../../components/RoutingShell";
|
||||
import SideBar from "../../components/SideBar";
|
||||
@@ -285,12 +285,8 @@ export default function FormEdit({
|
||||
form={form}
|
||||
appUrl={appUrl}
|
||||
heading={
|
||||
<PencilEdit
|
||||
value={
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
//@ts-ignore
|
||||
hookForm.watch("name")
|
||||
}
|
||||
<EditableHeading
|
||||
title={hookForm.watch("name")}
|
||||
onChange={(value) => {
|
||||
hookForm.setValue("name", value);
|
||||
}}
|
||||
|
||||
@@ -13,7 +13,7 @@ import { inferSSRProps } from "@calcom/types/inferSSRProps";
|
||||
import { Button } from "@calcom/ui";
|
||||
import { Label } from "@calcom/ui/form/fields";
|
||||
|
||||
import PencilEdit from "@components/PencilEdit";
|
||||
import EditableHeading from "@components/ui/EditableHeading";
|
||||
import { SelectWithValidation as Select } from "@components/ui/form/Select";
|
||||
|
||||
import RoutingShell from "../../components/RoutingShell";
|
||||
@@ -466,7 +466,10 @@ export default function RouteBuilder({
|
||||
appUrl,
|
||||
}: inferSSRProps<typeof getServerSideProps> & { appUrl: string }) {
|
||||
return (
|
||||
<RoutingShell appUrl={appUrl} heading={<PencilEdit value={form?.name} readOnly={true} />} form={form}>
|
||||
<RoutingShell
|
||||
appUrl={appUrl}
|
||||
heading={<EditableHeading title={form?.name} readOnly={true} />}
|
||||
form={form}>
|
||||
<div className="route-config">
|
||||
<Routes form={form} appUrl={appUrl} />
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user