Component store

This commit is contained in:
sean-brydon 2022-12-08 13:03:36 +00:00
parent f361eaea9b
commit c5733c0c9d
5 changed files with 85 additions and 12 deletions

View File

@ -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();

View File

@ -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<EventType>(
const grouped = groupBy<IEventTypeFilter>(
eventTypes.data.filter((el) => el.team),
(item) => item?.team?.name || ""
); // Add the team name

View File

@ -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 = () => {
<input
type="checkbox"
name=""
id=""
checked={
selectedUsers.filter(
(selected) => 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 "
/>
</div>

View File

@ -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<BookingLayoutStoreState & BookingLayoutStoreActions>((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({
<div className="flex flex-col lg:flex-row">
<HorizontalTabs tabs={tabs} />
<div className="flex space-x-2">
<TeamsMemberFilter />
<EventTypeFilter />
{/* <TeamsMemberFilter />
<EventTypeFilter /> */}
</div>
</div>
<main className="w-full max-w-6xl">{children}</main>

View File

@ -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"
}
}