From 7739994f4e24968b562e9caeb2339317f8e9d826 Mon Sep 17 00:00:00 2001 From: Bailey Pumfleet Date: Tue, 11 Jan 2022 10:32:40 +0000 Subject: [PATCH] Add an away mode to disable your booking page (#1418) * Add away column and status circle * Add away status toggle * Show message on booking page when away * Update common.json Co-authored-by: Peer Richelsen Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com> --- components/Shell.tsx | 34 ++++++++++++++- components/ui/Dropdown.tsx | 2 +- pages/[user].tsx | 42 ++++++++++++------- .../migration.sql | 2 + prisma/schema.prisma | 1 + public/static/locales/en/common.json | 6 ++- server/createContext.ts | 1 + server/routers/viewer.tsx | 17 ++++++++ 8 files changed, 86 insertions(+), 19 deletions(-) create mode 100644 prisma/migrations/20220105104913_add_away_field/migration.sql diff --git a/components/Shell.tsx b/components/Shell.tsx index caccb540..a1021287 100644 --- a/components/Shell.tsx +++ b/components/Shell.tsx @@ -8,6 +8,7 @@ import { LinkIcon, LogoutIcon, PuzzleIcon, + MoonIcon, } from "@heroicons/react/solid"; import { signOut, useSession } from "next-auth/react"; import Link from "next/link"; @@ -356,14 +357,25 @@ function UserDropdown({ small }: { small?: boolean }) { const { t } = useLocale(); const query = useMeQuery(); const user = query.data; + const mutation = trpc.useMutation("viewer.away"); + const utils = trpc.useContext(); return (
+ className={classNames( + small ? "w-8 h-8" : "w-10 h-10", + "bg-gray-300 rounded-full flex-shrink-0 relative" + )}> + {!user?.away && ( +
+ )} + {user?.away && ( +
+ )}
{!small && ( @@ -384,6 +396,26 @@ function UserDropdown({ small }: { small?: boolean }) {
+ + { + mutation.mutate({ away: !user?.away }); + utils.invalidateQueries("viewer.me"); + }} + className="flex px-4 py-2 text-sm cursor-pointer hover:bg-gray-100 hover:text-gray-900"> + + + {user?.username && ( {children} diff --git a/pages/[user].tsx b/pages/[user].tsx index 4dd7f396..d570eef5 100644 --- a/pages/[user].tsx +++ b/pages/[user].tsx @@ -1,4 +1,5 @@ import { ArrowRightIcon } from "@heroicons/react/outline"; +import { MoonIcon } from "@heroicons/react/solid"; import { GetServerSidePropsContext } from "next"; import Link from "next/link"; import { useRouter } from "next/router"; @@ -49,23 +50,31 @@ export default function User(props: inferSSRProps) {

{user.bio}

- {eventTypes.map((type) => ( -
- - - -

{type.title}

- -
- + {user.away && ( +
+ +

{t("user_away")}

+

{t("user_away_description")}

- ))} + )} + {!user.away && + eventTypes.map((type) => ( + + ))}
{eventTypes.length === 0 && (
@@ -102,6 +111,7 @@ export const getServerSideProps = async (context: GetServerSidePropsContext) => avatar: true, theme: true, plan: true, + away: true, }, }); diff --git a/prisma/migrations/20220105104913_add_away_field/migration.sql b/prisma/migrations/20220105104913_add_away_field/migration.sql new file mode 100644 index 00000000..7f2996fb --- /dev/null +++ b/prisma/migrations/20220105104913_add_away_field/migration.sql @@ -0,0 +1,2 @@ +-- AlterTable +ALTER TABLE "users" ADD COLUMN "away" BOOLEAN NOT NULL DEFAULT false; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index d5ddc4e8..6292d238 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -118,6 +118,7 @@ model User { brandColor String @default("#292929") // the location where the events will end up destinationCalendar DestinationCalendar? + away Boolean @default(false) metadata Json? @@map(name: "users") diff --git a/public/static/locales/en/common.json b/public/static/locales/en/common.json index 3c960f86..e3426473 100644 --- a/public/static/locales/en/common.json +++ b/public/static/locales/en/common.json @@ -570,5 +570,9 @@ "error_required_field": "This field is required.", "status": "Status", "team_view_user_availability": "View user availability", - "team_view_user_availability_disabled": "User needs to accept invite to view availability" + "team_view_user_availability_disabled": "User needs to accept invite to view availability", + "set_as_away": "Set yourself as away", + "set_as_free": "Disable away status", + "user_away": "This user is currently away.", + "user_away_description": "The person you are trying to book has set themselves to away, and therefore is not accepting new bookings." } diff --git a/server/createContext.ts b/server/createContext.ts index d56103d1..ac410c8c 100644 --- a/server/createContext.ts +++ b/server/createContext.ts @@ -45,6 +45,7 @@ async function getUserFromSession({ twoFactorEnabled: true, brandColor: true, plan: true, + away: true, credentials: { select: { id: true, diff --git a/server/routers/viewer.tsx b/server/routers/viewer.tsx index 86697941..c01eb20e 100644 --- a/server/routers/viewer.tsx +++ b/server/routers/viewer.tsx @@ -57,6 +57,7 @@ const loggedInViewerRouter = createProtectedRouter() twoFactorEnabled, brandColor, plan, + away, } = ctx.user; const me = { id, @@ -73,10 +74,26 @@ const loggedInViewerRouter = createProtectedRouter() twoFactorEnabled, brandColor, plan, + away, }; return me; }, }) + .mutation("away", { + input: z.object({ + away: z.boolean(), + }), + async resolve({ input, ctx }) { + await ctx.prisma.user.update({ + where: { + email: ctx.user.email, + }, + data: { + away: input.away, + }, + }); + }, + }) .query("eventTypes", { async resolve({ ctx }) { const { prisma } = ctx;