// TODO: replace headlessui with radix-ui
import { Menu, Transition } from "@headlessui/react";
import {
DotsHorizontalIcon,
ExternalLinkIcon,
LinkIcon,
ArrowDownIcon,
ChevronDownIcon,
PlusIcon,
ArrowUpIcon,
UsersIcon,
} from "@heroicons/react/solid";
import { SchedulingType } from "@prisma/client";
import Head from "next/head";
import Link from "next/link";
import { useRouter } from "next/router";
import React, { Fragment, useRef, useState, useEffect } from "react";
import { useMutation } from "react-query";
import { QueryCell } from "@lib/QueryCell";
import classNames from "@lib/classNames";
import { HttpError } from "@lib/core/http/error";
import { useLocale } from "@lib/hooks/useLocale";
import { useToggleQuery } from "@lib/hooks/useToggleQuery";
import createEventType from "@lib/mutations/event-types/create-event-type";
import showToast from "@lib/notification";
import { inferQueryOutput, trpc } from "@lib/trpc";
import { CreateEventType } from "@lib/types/event-type";
import { Dialog, DialogClose, DialogContent } from "@components/Dialog";
import Shell from "@components/Shell";
import { Tooltip } from "@components/Tooltip";
import EventTypeDescription from "@components/eventtype/EventTypeDescription";
import { Alert } from "@components/ui/Alert";
import Avatar from "@components/ui/Avatar";
import AvatarGroup from "@components/ui/AvatarGroup";
import Badge from "@components/ui/Badge";
import { Button } from "@components/ui/Button";
import Dropdown, {
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuLabel,
DropdownMenuSeparator,
DropdownMenuTrigger,
} from "@components/ui/Dropdown";
import * as RadioArea from "@components/ui/form/radio-area";
import UserCalendarIllustration from "@components/ui/svg/UserCalendarIllustration";
type Profiles = inferQueryOutput<"viewer.eventTypes">["profiles"];
type EventTypeGroups = inferQueryOutput<"viewer.eventTypes">["eventTypeGroups"];
type EventTypeGroupProfile = EventTypeGroups[number]["profile"];
interface CreateEventTypeProps {
canAddEvents: boolean;
profiles: Profiles;
}
const CreateFirstEventTypeView = ({ canAddEvents, profiles }: CreateEventTypeProps) => {
const { t } = useLocale();
return (
{t("new_event_type_heading")}
{t("new_event_type_description")}
);
};
type EventTypeGroup = inferQueryOutput<"viewer.eventTypes">["eventTypeGroups"][number];
type EventType = EventTypeGroup["eventTypes"][number];
interface EventTypeListProps {
profile: { slug: string | null };
readOnly: boolean;
types: EventType[];
}
const EventTypeList = ({ readOnly, types, profile }: EventTypeListProps): JSX.Element => {
const { t } = useLocale();
const utils = trpc.useContext();
const mutation = trpc.useMutation("viewer.eventTypeOrder", {
onError: (err) => {
console.error(err.message);
},
async onSettled() {
await utils.cancelQuery(["viewer.eventTypes"]);
await utils.invalidateQueries(["viewer.eventTypes"]);
},
});
const [sortableTypes, setSortableTypes] = useState(types);
useEffect(() => {
setSortableTypes(types);
}, [types]);
function moveEventType(index: number, increment: 1 | -1) {
const newList = [...sortableTypes];
const type = sortableTypes[index];
const tmp = sortableTypes[index + increment];
if (tmp) {
newList[index] = tmp;
newList[index + increment] = type;
}
setSortableTypes(newList);
mutation.mutate({
ids: newList.map((type) => type.id),
});
}
return (
{sortableTypes.map((type, index) => (
-
))}
);
};
interface EventTypeListHeadingProps {
profile: EventTypeGroupProfile;
membershipCount: number;
}
const EventTypeListHeading = ({ profile, membershipCount }: EventTypeListHeadingProps): JSX.Element => (
);
const EventTypesPage = () => {
const { t } = useLocale();
const query = trpc.useQuery(["viewer.eventTypes"]);
return (
Home | Cal.com
)
}>
(
<>
{data.user.plan === "FREE" && !data.canAddEvents && (
{t("plan_upgrade")}>}
message={
<>
{t("to_upgrade_go_to")}{" "}
{"https://cal.com/upgrade"}
>
}
className="mb-4"
/>
)}
{data.eventTypeGroups &&
data.eventTypeGroups.map((input) => (
{/* hide list heading when there is only one (current user) */}
{(data.eventTypeGroups.length !== 1 || input.teamId) && (
)}
))}
{data.eventTypeGroups.length === 0 && (
)}
>
)}
/>
);
};
const CreateNewEventButton = ({ profiles, canAddEvents }: CreateEventTypeProps) => {
const router = useRouter();
const teamId: number | null = Number(router.query.teamId) || null;
const modalOpen = useToggleQuery("new");
const { t } = useLocale();
const createMutation = useMutation(createEventType, {
onSuccess: async ({ eventType }) => {
await router.push("/event-types/" + eventType.id);
showToast(t("event_type_created_successfully", { eventTypeTitle: eventType.title }), "success");
},
onError: (err: HttpError) => {
const message = `${err.statusCode}: ${err.message}`;
showToast(message, "error");
},
});
const slugRef = useRef(null);
return (
);
};
export default EventTypesPage;