Old teams page in v2 (#4553)
* Old teams page in v2 * Tea nav item fix * Team creation modal converted to v2 * Updated emptyscreen and shell button Co-authored-by: Peer Richelsen <peeroke@gmail.com>pull/4486/head^2
parent
00071bcdf0
commit
1b2707d4f0
|
@ -3,9 +3,9 @@ import { useRef, useState } from "react";
|
||||||
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||||
import { trpc } from "@calcom/trpc/react";
|
import { trpc } from "@calcom/trpc/react";
|
||||||
import { Button } from "@calcom/ui";
|
import { Button } from "@calcom/ui";
|
||||||
import { Alert } from "@calcom/ui/Alert";
|
|
||||||
import { Dialog, DialogContent, DialogFooter } from "@calcom/ui/Dialog";
|
|
||||||
import { Icon } from "@calcom/ui/Icon";
|
import { Icon } from "@calcom/ui/Icon";
|
||||||
|
import { Alert } from "@calcom/ui/v2/core/Alert";
|
||||||
|
import { Dialog, DialogContent, DialogFooter } from "@calcom/ui/v2/core/Dialog";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
isOpen: boolean;
|
isOpen: boolean;
|
||||||
|
@ -28,15 +28,14 @@ export default function TeamCreate(props: Props) {
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const createTeam = (e: React.FormEvent<HTMLFormElement>) => {
|
const createTeam = () => {
|
||||||
e.preventDefault();
|
|
||||||
createTeamMutation.mutate({ name: nameRef?.current?.value });
|
createTeamMutation.mutate({ name: nameRef?.current?.value });
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Dialog open={props.isOpen} onOpenChange={props.onClose}>
|
<Dialog open={props.isOpen} onOpenChange={props.onClose}>
|
||||||
<DialogContent>
|
<DialogContent type="creation" actionText={t("create_new_team")} actionOnClick={createTeam}>
|
||||||
<div className="mb-4 sm:flex sm:items-start">
|
<div className="mb-4 sm:flex sm:items-start">
|
||||||
<div className="bg-brand text-brandcontrast dark:bg-darkmodebrand dark:text-darkmodebrandcontrast mx-auto flex h-12 w-12 flex-shrink-0 items-center justify-center rounded-full bg-opacity-5 sm:mx-0 sm:h-10 sm:w-10">
|
<div className="bg-brand text-brandcontrast dark:bg-darkmodebrand dark:text-darkmodebrandcontrast mx-auto flex h-12 w-12 flex-shrink-0 items-center justify-center rounded-full bg-opacity-5 sm:mx-0 sm:h-10 sm:w-10">
|
||||||
<Icon.FiUsers className="text-brandcontrast h-6 w-6" />
|
<Icon.FiUsers className="text-brandcontrast h-6 w-6" />
|
||||||
|
@ -50,7 +49,7 @@ export default function TeamCreate(props: Props) {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<form onSubmit={createTeam}>
|
<form>
|
||||||
<div className="mb-4">
|
<div className="mb-4">
|
||||||
<label htmlFor="name" className="block text-sm font-medium text-gray-700">
|
<label htmlFor="name" className="block text-sm font-medium text-gray-700">
|
||||||
{t("name")}
|
{t("name")}
|
||||||
|
@ -66,18 +65,6 @@ export default function TeamCreate(props: Props) {
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
{errorMessage && <Alert severity="error" title={errorMessage} />}
|
{errorMessage && <Alert severity="error" title={errorMessage} />}
|
||||||
<DialogFooter>
|
|
||||||
<Button type="button" color="secondary" onClick={props.onClose}>
|
|
||||||
{t("cancel")}
|
|
||||||
</Button>
|
|
||||||
<Button
|
|
||||||
type="submit"
|
|
||||||
color="primary"
|
|
||||||
className="ltr:ml-2 rtl:mr-2"
|
|
||||||
data-testid="create-new-team-button">
|
|
||||||
{t("create_team")}
|
|
||||||
</Button>
|
|
||||||
</DialogFooter>
|
|
||||||
</form>
|
</form>
|
||||||
</DialogContent>
|
</DialogContent>
|
||||||
</Dialog>
|
</Dialog>
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
|
|
||||||
import showToast from "@calcom/lib/notification";
|
|
||||||
import { inferQueryOutput, trpc } from "@calcom/trpc/react";
|
import { inferQueryOutput, trpc } from "@calcom/trpc/react";
|
||||||
|
import showToast from "@calcom/ui/v2/core/notifications";
|
||||||
|
|
||||||
import TeamListItem from "./TeamListItem";
|
import TeamListItem from "./TeamListItem";
|
||||||
|
|
||||||
|
|
|
@ -4,19 +4,19 @@ import Link from "next/link";
|
||||||
import classNames from "@calcom/lib/classNames";
|
import classNames from "@calcom/lib/classNames";
|
||||||
import { getPlaceholderAvatar } from "@calcom/lib/getPlaceholderAvatar";
|
import { getPlaceholderAvatar } from "@calcom/lib/getPlaceholderAvatar";
|
||||||
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||||
import showToast from "@calcom/lib/notification";
|
|
||||||
import { inferQueryOutput, trpc } from "@calcom/trpc/react";
|
import { inferQueryOutput, trpc } from "@calcom/trpc/react";
|
||||||
import Button from "@calcom/ui/Button";
|
import { Icon } from "@calcom/ui/Icon";
|
||||||
import ConfirmationDialogContent from "@calcom/ui/ConfirmationDialogContent";
|
import Button from "@calcom/ui/v2/core/Button";
|
||||||
import { Dialog, DialogTrigger } from "@calcom/ui/Dialog";
|
import ConfirmationDialogContent from "@calcom/ui/v2/core/ConfirmationDialogContent";
|
||||||
|
import { Dialog, DialogTrigger } from "@calcom/ui/v2/core/Dialog";
|
||||||
import Dropdown, {
|
import Dropdown, {
|
||||||
DropdownMenuContent,
|
DropdownMenuContent,
|
||||||
DropdownMenuItem,
|
DropdownMenuItem,
|
||||||
DropdownMenuSeparator,
|
DropdownMenuSeparator,
|
||||||
DropdownMenuTrigger,
|
DropdownMenuTrigger,
|
||||||
} from "@calcom/ui/Dropdown";
|
} from "@calcom/ui/v2/core/Dropdown";
|
||||||
import { Icon } from "@calcom/ui/Icon";
|
import { Tooltip } from "@calcom/ui/v2/core/Tooltip";
|
||||||
import { Tooltip } from "@calcom/ui/Tooltip";
|
import showToast from "@calcom/ui/v2/core/notifications";
|
||||||
|
|
||||||
import Avatar from "@components/ui/Avatar";
|
import Avatar from "@components/ui/Avatar";
|
||||||
|
|
||||||
|
@ -84,7 +84,7 @@ export default function TeamListItem(props: Props) {
|
||||||
!isInvitee && "group hover:bg-neutral-50"
|
!isInvitee && "group hover:bg-neutral-50"
|
||||||
)}>
|
)}>
|
||||||
{!isInvitee ? (
|
{!isInvitee ? (
|
||||||
<Link href={"/settings/teams/" + team.id}>
|
<Link href={"/settings/teams/" + team.id + "/profile"}>
|
||||||
<a className="flex-grow cursor-pointer truncate text-sm" title={`${team.name}`}>
|
<a className="flex-grow cursor-pointer truncate text-sm" title={`${team.name}`}>
|
||||||
{teamInfo}
|
{teamInfo}
|
||||||
</a>
|
</a>
|
||||||
|
@ -112,7 +112,6 @@ export default function TeamListItem(props: Props) {
|
||||||
<DropdownMenuItem>
|
<DropdownMenuItem>
|
||||||
<Button
|
<Button
|
||||||
color="minimal"
|
color="minimal"
|
||||||
size="sm"
|
|
||||||
className="w-full rounded-none font-medium"
|
className="w-full rounded-none font-medium"
|
||||||
StartIcon={Icon.FiCheck}
|
StartIcon={Icon.FiCheck}
|
||||||
onClick={acceptInvite}>
|
onClick={acceptInvite}>
|
||||||
|
@ -121,8 +120,7 @@ export default function TeamListItem(props: Props) {
|
||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
<DropdownMenuItem>
|
<DropdownMenuItem>
|
||||||
<Button
|
<Button
|
||||||
color="warn"
|
color="destructive"
|
||||||
size="sm"
|
|
||||||
className="w-full rounded-none font-medium"
|
className="w-full rounded-none font-medium"
|
||||||
StartIcon={Icon.FiX}
|
StartIcon={Icon.FiX}
|
||||||
onClick={declineInvite}>
|
onClick={declineInvite}>
|
||||||
|
@ -158,11 +156,10 @@ export default function TeamListItem(props: Props) {
|
||||||
<DropdownMenuContent hidden={hideDropdown}>
|
<DropdownMenuContent hidden={hideDropdown}>
|
||||||
{isAdmin && (
|
{isAdmin && (
|
||||||
<DropdownMenuItem>
|
<DropdownMenuItem>
|
||||||
<Link href={"/settings/teams/" + team.id}>
|
<Link href={"/settings/teams/" + team.id + "/profile"}>
|
||||||
<a>
|
<a>
|
||||||
<Button
|
<Button
|
||||||
color="minimal"
|
color="minimal"
|
||||||
size="sm"
|
|
||||||
className="w-full rounded-none font-medium"
|
className="w-full rounded-none font-medium"
|
||||||
StartIcon={Icon.FiEdit2}>
|
StartIcon={Icon.FiEdit2}>
|
||||||
{t("edit_team")}
|
{t("edit_team")}
|
||||||
|
@ -176,7 +173,6 @@ export default function TeamListItem(props: Props) {
|
||||||
<a target="_blank">
|
<a target="_blank">
|
||||||
<Button
|
<Button
|
||||||
color="minimal"
|
color="minimal"
|
||||||
size="sm"
|
|
||||||
className="w-full rounded-none font-medium"
|
className="w-full rounded-none font-medium"
|
||||||
StartIcon={Icon.FiExternalLink}>
|
StartIcon={Icon.FiExternalLink}>
|
||||||
{t("preview_team")}
|
{t("preview_team")}
|
||||||
|
@ -193,8 +189,7 @@ export default function TeamListItem(props: Props) {
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
}}
|
}}
|
||||||
color="warn"
|
color="destructive"
|
||||||
size="sm"
|
|
||||||
className="w-full rounded-none font-medium"
|
className="w-full rounded-none font-medium"
|
||||||
StartIcon={Icon.FiTrash}>
|
StartIcon={Icon.FiTrash}>
|
||||||
{t("disband_team")}
|
{t("disband_team")}
|
||||||
|
@ -220,7 +215,7 @@ export default function TeamListItem(props: Props) {
|
||||||
<DialogTrigger asChild>
|
<DialogTrigger asChild>
|
||||||
<Button
|
<Button
|
||||||
type="button"
|
type="button"
|
||||||
color="warn"
|
color="destructive"
|
||||||
size="lg"
|
size="lg"
|
||||||
StartIcon={Icon.FiLogOut}
|
StartIcon={Icon.FiLogOut}
|
||||||
className="w-full rounded-none"
|
className="w-full rounded-none"
|
||||||
|
|
|
@ -17,6 +17,7 @@ const V2_WHITELIST = [
|
||||||
"/event-types",
|
"/event-types",
|
||||||
"/workflows",
|
"/workflows",
|
||||||
"/apps",
|
"/apps",
|
||||||
|
"/teams",
|
||||||
"/success",
|
"/success",
|
||||||
"/auth/login",
|
"/auth/login",
|
||||||
];
|
];
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
import UserV2OptInBanner from "@calcom/features/users/components/UserV2OptInBanner";
|
|
||||||
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||||
import { MobileNavigationMoreItems } from "@calcom/ui/Shell";
|
import { MobileNavigationMoreItems } from "@calcom/ui/Shell";
|
||||||
import { Shell } from "@calcom/ui/v2";
|
import { Shell } from "@calcom/ui/v2";
|
||||||
|
|
|
@ -0,0 +1,72 @@
|
||||||
|
import { useState } from "react";
|
||||||
|
|
||||||
|
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||||
|
import { trpc } from "@calcom/trpc/react";
|
||||||
|
import { Icon } from "@calcom/ui/Icon";
|
||||||
|
import { Shell } from "@calcom/ui/v2";
|
||||||
|
import { Alert } from "@calcom/ui/v2/core/Alert";
|
||||||
|
import Button from "@calcom/ui/v2/core/Button";
|
||||||
|
import EmptyScreen from "@calcom/ui/v2/core/EmptyScreen";
|
||||||
|
|
||||||
|
import SkeletonLoaderTeamList from "@components/team/SkeletonloaderTeamList";
|
||||||
|
import TeamCreateModal from "@components/team/TeamCreateModal";
|
||||||
|
import TeamList from "@components/team/TeamList";
|
||||||
|
|
||||||
|
function Teams() {
|
||||||
|
const { t } = useLocale();
|
||||||
|
const [showCreateTeamModal, setShowCreateTeamModal] = useState(false);
|
||||||
|
const [errorMessage, setErrorMessage] = useState("");
|
||||||
|
|
||||||
|
const { data, isLoading } = trpc.useQuery(["viewer.teams.list"], {
|
||||||
|
onError: (e) => {
|
||||||
|
setErrorMessage(e.message);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const teams = data?.filter((m) => m.accepted) || [];
|
||||||
|
const invites = data?.filter((m) => !m.accepted) || [];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Shell
|
||||||
|
heading={t("teams")}
|
||||||
|
subtitle={t("create_manage_teams_collaborative")}
|
||||||
|
CTA={
|
||||||
|
<Button type="button" onClick={() => setShowCreateTeamModal(true)}>
|
||||||
|
<Icon.FiPlus className="inline-block h-3.5 w-3.5 text-white group-hover:text-black ltr:mr-2 rtl:ml-2" />
|
||||||
|
{t("new")}
|
||||||
|
</Button>
|
||||||
|
}>
|
||||||
|
<>
|
||||||
|
{!!errorMessage && <Alert severity="error" title={errorMessage} />}
|
||||||
|
{showCreateTeamModal && (
|
||||||
|
<TeamCreateModal isOpen={showCreateTeamModal} onClose={() => setShowCreateTeamModal(false)} />
|
||||||
|
)}
|
||||||
|
{invites.length > 0 && (
|
||||||
|
<div className="mb-4">
|
||||||
|
<h1 className="mb-2 text-lg font-medium">{t("open_invitations")}</h1>
|
||||||
|
<TeamList teams={invites} />
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{isLoading && <SkeletonLoaderTeamList />}
|
||||||
|
{!teams.length && !isLoading && (
|
||||||
|
<EmptyScreen
|
||||||
|
Icon={Icon.FiUsers}
|
||||||
|
headline={t("no_teams")}
|
||||||
|
description={t("no_teams_description")}
|
||||||
|
buttonRaw={
|
||||||
|
<Button color="secondary" onClick={() => setShowCreateTeamModal(true)}>
|
||||||
|
{t("create_team")}
|
||||||
|
</Button>
|
||||||
|
}
|
||||||
|
buttonOnClick={() => setShowCreateTeamModal(true)}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{teams.length > 0 && <TeamList teams={teams} />}
|
||||||
|
</>
|
||||||
|
</Shell>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Teams.requiresLicense = false;
|
||||||
|
|
||||||
|
export default Teams;
|
|
@ -382,6 +382,8 @@ export type NavigationItemType = {
|
||||||
icon?: SVGComponent;
|
icon?: SVGComponent;
|
||||||
child?: NavigationItemType[];
|
child?: NavigationItemType[];
|
||||||
pro?: true;
|
pro?: true;
|
||||||
|
onlyMobile?: boolean;
|
||||||
|
onlyDesktop?: boolean;
|
||||||
isCurrent?: ({
|
isCurrent?: ({
|
||||||
item,
|
item,
|
||||||
isChild,
|
isChild,
|
||||||
|
@ -411,6 +413,12 @@ const navigation: NavigationItemType[] = [
|
||||||
href: "/availability",
|
href: "/availability",
|
||||||
icon: Icon.FiClock,
|
icon: Icon.FiClock,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "teams",
|
||||||
|
href: "/teams",
|
||||||
|
icon: Icon.FiUsers,
|
||||||
|
onlyDesktop: true,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "apps",
|
name: "apps",
|
||||||
href: "/apps",
|
href: "/apps",
|
||||||
|
@ -480,7 +488,7 @@ const { desktopNavigationItems, mobileNavigationBottomItems, mobileNavigationMor
|
||||||
// We filter out the "more" separator in desktop navigation
|
// We filter out the "more" separator in desktop navigation
|
||||||
if (item.name !== MORE_SEPARATOR_NAME) items.desktopNavigationItems.push(item);
|
if (item.name !== MORE_SEPARATOR_NAME) items.desktopNavigationItems.push(item);
|
||||||
// Items for mobile bottom navigation
|
// Items for mobile bottom navigation
|
||||||
if (index < moreSeparatorIndex + 1) items.mobileNavigationBottomItems.push(item);
|
if (index < moreSeparatorIndex + 1 && !item.onlyDesktop) items.mobileNavigationBottomItems.push(item);
|
||||||
// Items for the "more" menu in mobile navigation
|
// Items for the "more" menu in mobile navigation
|
||||||
else items.mobileNavigationMoreItems.push(item);
|
else items.mobileNavigationMoreItems.push(item);
|
||||||
return items;
|
return items;
|
||||||
|
|
Loading…
Reference in New Issue