Fix 404 error when editing default availability & create new availability from event type page (#5085)

* Edit/create new availability

* Connect new schedule to event type

* Remove comment

* Shell back button executes window.history.back

* Fix default schedule

* Add default badge

* Fix type error
This commit is contained in:
Joe Au-Yeung
2022-10-24 18:29:49 -06:00
committed by GitHub
parent 16eb516a9b
commit 317909d20a
6 changed files with 68 additions and 6 deletions
@@ -1,5 +1,6 @@
import { FormValues } from "pages/event-types/[type]";
import { Controller, useFormContext } from "react-hook-form";
import { SingleValueProps, OptionProps, components } from "react-select";
import dayjs from "@calcom/dayjs";
import classNames from "@calcom/lib/classNames";
@@ -7,6 +8,7 @@ import { useLocale } from "@calcom/lib/hooks/useLocale";
import { weekdayNames } from "@calcom/lib/weekday";
import { trpc } from "@calcom/trpc/react";
import { Icon } from "@calcom/ui";
import { Badge } from "@calcom/ui/v2";
import Button from "@calcom/ui/v2/core/Button";
import Select from "@calcom/ui/v2/core/form/select";
import { SkeletonText } from "@calcom/ui/v2/core/skeleton";
@@ -16,6 +18,35 @@ import { SelectSkeletonLoader } from "@components/v2/availability/SkeletonLoader
type AvailabilityOption = {
label: string;
value: number;
isDefault: boolean;
};
const Option = ({ ...props }: OptionProps<AvailabilityOption>) => {
const { label, isDefault } = props.data;
return (
<components.Option {...props}>
<span>{label}</span>
{isDefault && (
<Badge variant="blue" className="ml-2">
Default
</Badge>
)}
</components.Option>
);
};
const SingleValue = ({ ...props }: SingleValueProps<AvailabilityOption>) => {
const { label, isDefault } = props.data;
return (
<components.SingleValue {...props}>
<span>{label}</span>
{isDefault && (
<Badge variant="blue" className="ml-2">
Default
</Badge>
)}
</components.SingleValue>
);
};
const AvailabilitySelect = ({
@@ -38,6 +69,7 @@ const AvailabilitySelect = ({
const options = schedules.map((schedule) => ({
value: schedule.id,
label: schedule.name,
isDefault: schedule.isDefault,
}));
const value = options.find((option) =>
@@ -53,6 +85,8 @@ const AvailabilitySelect = ({
onChange={props.onChange}
className={classNames("block w-full min-w-0 flex-1 rounded-sm text-sm", className)}
value={value}
components={{ Option, SingleValue }}
isMulti={false}
/>
);
};
@@ -130,7 +164,7 @@ export const AvailabilityTab = () => {
{schedule?.timeZone || <SkeletonText className="block h-5 w-32" />}
</span>
<Button
href={`/availability/${scheduleId}`}
href={`/availability/${schedule?.schedule.id}`}
color="minimal"
EndIcon={Icon.FiExternalLink}
target="_blank"
+1 -1
View File
@@ -162,7 +162,7 @@ export default function Availability({ schedule }: { schedule: number }) {
</div>
</div>
<div className="min-w-40 col-span-3 space-y-2 lg:col-span-1">
<div className="xl:max-w-80 w-full pr-4 sm:p-0">
<div className="xl:max-w-80 mt-4 w-full pr-4 sm:p-0">
<div>
<label htmlFor="timeZone" className="block text-sm font-medium text-gray-700">
{t("timezone")}
@@ -1309,6 +1309,8 @@
"cant_find_the_right_video_app_visit_our_app_store": "Can't find the right video app? Visit our <1>App Store</1>.",
"install_new_calendar_app": "Install new calendar app",
"make_phone_number_required": "Make phone number required for booking event",
"new_event_type_availability": "{{eventTypeTitle}} Availability",
"error_editing_availability": "Error editing availability",
"dont_have_permission": "You don't have permission to access this resource.",
"saml_config": "Single Sign-On",
"saml_description": "Allow team members to login using an Identity Provider",
@@ -15,6 +15,7 @@ export const availabilityRouter = createProtectedRouter()
.query("list", {
async resolve({ ctx }) {
const { prisma, user } = ctx;
const schedules = await prisma.schedule.findMany({
where: {
userId: user.id,
@@ -29,10 +30,13 @@ export const availabilityRouter = createProtectedRouter()
id: "asc",
},
});
const defaultScheduleId = await getDefaultScheduleId(user.id, prisma);
return {
schedules: schedules.map((schedule) => ({
...schedule,
isDefault: user.defaultScheduleId === schedule.id || schedules.length === 1,
isDefault: schedule.id === defaultScheduleId,
})),
};
},
@@ -102,6 +106,7 @@ export const availabilityRouter = createProtectedRouter()
)
)
.optional(),
eventTypeId: z.number().optional(),
}),
async resolve({ input, ctx }) {
const { user, prisma } = ctx;
@@ -112,6 +117,8 @@ export const availabilityRouter = createProtectedRouter()
id: user.id,
},
},
// If an eventTypeId is provided then connect the new schedule to that event type
...(input.eventTypeId && { eventType: { connect: { id: input.eventTypeId } } }),
};
const availability = getAvailabilityFromSchedule(input.schedule || DEFAULT_SCHEDULE);
+4 -2
View File
@@ -170,7 +170,7 @@ type LayoutProps = {
TopNavContainer?: ReactNode;
drawerState?: DrawerState;
HeadingLeftIcon?: ReactNode;
backPath?: string; // renders back button to specified path
backPath?: string | boolean; // renders back button to specified path
// use when content needs to expand with flex
flexChildrenContainer?: boolean;
isPublic?: boolean;
@@ -773,7 +773,9 @@ export function ShellMain(props: LayoutProps) {
<Button
size="icon"
color="minimal"
onClick={() => router.push(props.backPath as string)}
onClick={() =>
typeof props.backPath === "string" ? router.push(props.backPath as string) : router.back()
}
StartIcon={Icon.FiArrowLeft}
aria-label="Go Back"
className="ltr:mr-2 rtl:ml-2"
+18 -1
View File
@@ -71,7 +71,24 @@ const Select = <
return getReactSelectProps<Option, IsMulti, Group>({ className, components: components || {} });
}, [className, components]);
return <ReactSelect {...reactSelectProps} {...props} />;
return (
<ReactSelect
{...reactSelectProps}
{...props}
styles={{
option: (defaultStyles, state) => ({
...defaultStyles,
backgroundColor: state.isSelected
? state.isFocused
? "var(--brand-color)"
: "var(--brand-color)"
: state.isFocused
? "var(--brand-color-dark-mode)"
: "var(--brand-text-color)",
}),
}}
/>
);
};
export const SelectField = function SelectField<