diff --git a/apps/web/pages/bookings/[status].tsx b/apps/web/pages/bookings/[status].tsx index 2277a195cd..ab7a348568 100644 --- a/apps/web/pages/bookings/[status].tsx +++ b/apps/web/pages/bookings/[status].tsx @@ -5,7 +5,7 @@ import { Fragment } from "react"; import { z } from "zod"; import { WipeMyCalActionButton } from "@calcom/app-store/wipemycalother/components"; -import BookingLayout from "@calcom/features/bookings/layout/BookingLayout"; +import BookingLayout, { useFilterStore } from "@calcom/features/bookings/layout/BookingLayout"; import { useLocale } from "@calcom/lib/hooks/useLocale"; import { RouterInputs, RouterOutputs, trpc } from "@calcom/trpc/react"; import { Alert, Button, EmptyScreen, Icon } from "@calcom/ui"; @@ -42,6 +42,7 @@ const querySchema = z.object({ }); export default function Bookings() { + // const selectedUsers = useFilterStore((state) => state.selectedUsers); const router = useRouter(); const { status } = router.isReady ? querySchema.parse(router.query) : { status: "upcoming" as const }; const { t } = useLocale(); diff --git a/packages/features/bookings/components/EventTypeFilter.tsx b/packages/features/bookings/components/EventTypeFilter.tsx index cf416d5336..02b72e8e80 100644 --- a/packages/features/bookings/components/EventTypeFilter.tsx +++ b/packages/features/bookings/components/EventTypeFilter.tsx @@ -7,8 +7,8 @@ import { AnimatedPopover } from "@calcom/ui"; import { groupBy } from "../groupBy"; -type EventTypes = RouterOutputs["viewer"]["eventTypes"]["listWithTeam"]; -type EventType = EventTypes[0]; +export type IEventTypesFilters = RouterOutputs["viewer"]["eventTypes"]["listWithTeam"]; +export type IEventTypeFilter = IEventTypesFilters[0]; type GroupedEventTypeState = Record< string, @@ -32,7 +32,7 @@ export const EventTypeFilter = () => { useEffect(() => { if (eventTypes.data) { // Group event types by team - const grouped = groupBy( + const grouped = groupBy( eventTypes.data.filter((el) => el.team), (item) => item?.team?.name || "" ); // Add the team name diff --git a/packages/features/bookings/components/TeamsMemberFilter.tsx b/packages/features/bookings/components/TeamsMemberFilter.tsx index 699ade6e7f..520b80107e 100644 --- a/packages/features/bookings/components/TeamsMemberFilter.tsx +++ b/packages/features/bookings/components/TeamsMemberFilter.tsx @@ -1,10 +1,24 @@ import { Fragment } from "react"; +import shallow from "zustand/shallow"; import { useLocale } from "@calcom/lib/hooks/useLocale"; -import { trpc } from "@calcom/trpc/react"; +import { RouterOutputs, trpc } from "@calcom/trpc/react"; import { AnimatedPopover, Avatar } from "@calcom/ui"; +import { useFilterStore } from "../layout/BookingLayout"; + +export type ITeamMemberFilters = RouterOutputs["viewer"]["teams"]["listTeamsandMembers"]; +export type ITeamMemberFilter = ITeamMemberFilters[0]; + export const TeamsMemberFilter = () => { + const { selectedUsers, pushSelectedUser, removeSelectedUser } = useFilterStore( + (state) => ({ + selectedUsers: state.selectedUsers, + pushSelectedUser: state.pushSelectedUser, + removeSelectedUser: state.removeSelectedUser, + }), + shallow + ); const { t } = useLocale(); const { data } = trpc.viewer.teams.listTeamsandMembers.useQuery(); // Will be handled up the tree to redirect @@ -34,8 +48,19 @@ export const TeamsMemberFilter = () => { selected.id === team.id && selected.user.id === member.user.id + ).length > 0 + } + name={`${member.team.id}-${member.user.id}`} + onChange={(e) => { + if (e.target.checked) { + pushSelectedUser({ id: team.id, teamName: team.name, user: member.user }); + } else if (!e.target.checked) { + removeSelectedUser(member.user.id); + } + }} className="text-primary-600 focus:ring-primary-500 inline-flex h-4 w-4 place-self-center justify-self-end rounded border-gray-300 " /> diff --git a/packages/features/bookings/layout/BookingLayout.tsx b/packages/features/bookings/layout/BookingLayout.tsx index cfd7862ccf..7654e00941 100644 --- a/packages/features/bookings/layout/BookingLayout.tsx +++ b/packages/features/bookings/layout/BookingLayout.tsx @@ -1,10 +1,11 @@ import React, { ComponentProps } from "react"; +import create from "zustand"; import { HorizontalTabs, Shell } from "@calcom/ui"; import { VerticalTabItemProps, HorizontalTabItemProps } from "@calcom/ui/v2"; -import { EventTypeFilter } from "../components/EventTypeFilter"; -import { TeamsMemberFilter } from "../components/TeamsMemberFilter"; +import { EventTypeFilter, IEventTypeFilter } from "../components/EventTypeFilter"; +import { TeamsMemberFilter, ITeamMemberFilter } from "../components/TeamsMemberFilter"; const tabs: (VerticalTabItemProps | HorizontalTabItemProps)[] = [ { @@ -29,6 +30,51 @@ const tabs: (VerticalTabItemProps | HorizontalTabItemProps)[] = [ }, ]; +interface BookingLayoutStoreState { + selectedEventTypes: IEventTypeFilter[]; + selectedUsers: { + id: number; + teamName: string; + user: ITeamMemberFilter["members"][0]["user"]; + }[]; +} +interface BookingLayoutStoreActions { + setSelectedEventTypes: (eventTypes: IEventTypeFilter[]) => void; + setSelectedUsers: (users: BookingLayoutStoreState["selectedUsers"]) => void; + pushSelectedEventType: (eventType: IEventTypeFilter) => void; + pushSelectedUser: (user: BookingLayoutStoreState["selectedUsers"][0]) => void; + removeSelectedEventType: (eventType: IEventTypeFilter) => void; + removeSelectedUser: (userId: number) => void; + clearState: () => void; +} + +// Since this is a layout i thought i'd be best to implement some "Global" component state +export const useFilterStore = create((set) => ({ + selectedEventTypes: [], + selectedUsers: [], + setSelectedEventTypes: (eventTypes) => set({ selectedEventTypes: eventTypes }), + setSelectedUsers: (users) => set({ selectedUsers: users }), + pushSelectedEventType: (eventType) => { + set((state) => ({ selectedEventTypes: [...state.selectedEventTypes, eventType] })); + }, + pushSelectedUser: (user) => { + set((state) => ({ selectedUsers: [...state.selectedUsers, user] })); + }, + removeSelectedEventType: (eventType) => { + set((state) => ({ + selectedEventTypes: state.selectedEventTypes.filter((type) => type.id !== eventType.id), + })); + }, + removeSelectedUser: (userId) => { + set((state) => { + return { + selectedUsers: state.selectedUsers.filter((selected) => selected.user.id !== userId), + }; + }); + }, + clearState: () => set({ selectedEventTypes: [], selectedUsers: [] }), +})); + export default function BookingLayout({ children, ...rest @@ -39,8 +85,8 @@ export default function BookingLayout({
- - + {/* + */}
{children}
diff --git a/packages/features/package.json b/packages/features/package.json index 0d220f2ce4..c0e2152ca0 100644 --- a/packages/features/package.json +++ b/packages/features/package.json @@ -7,6 +7,7 @@ "main": "index.ts", "dependencies": { "@lexical/react": "^0.5.0", - "lexical": "^0.5.0" + "lexical": "^0.5.0", + "zustand": "^4.1.5" } }